mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
* P25 Phase 2 now supports control channel decoding and decoder was enhanced to improve decodes. * Radio reference site editor updated for phase 2 sites to allow user to select FDMA or TDMA control. * Decode events are now minimized and de-duplicated. * Fully parsing all phase 1/2 messages from the latest ICD. * Vendor specific messaging recoveries (Moto & Harris). * Patch group management enhancements with stale patch detection. * Tuner editor now fully resets the min/max frequency values * Default traffic channel count increased to 20 (from 3). * ISSI roaming radio and talkgroup values now displayed and aliasable as fully qualified values (e.g. 1234(123.456.7890) * Moto emergency alarm activation messaging support * Expanded list of P25 encryption algorithms * Message (bits) viewer enhanced for P25 phase 1 and phase 2 * IPV4 addresses and UDP ports no longer classified as user values - won't display in event views. * New framework for describing message binary fields that should reduce overall memory footprint and enhance code readability Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
@@ -32,6 +32,7 @@ import io.github.dsheirer.controller.channel.map.ChannelMapModel;
|
||||
import io.github.dsheirer.filter.AllPassFilter;
|
||||
import io.github.dsheirer.filter.FilterSet;
|
||||
import io.github.dsheirer.filter.IFilter;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroupManager;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.module.Module;
|
||||
@@ -51,6 +52,7 @@ import io.github.dsheirer.module.decode.dmr.audio.DMRAudioModule;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.DMRChannel;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.DMRLsn;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.DmrRestLsn;
|
||||
import io.github.dsheirer.module.decode.dmr.message.DMRMessage;
|
||||
import io.github.dsheirer.module.decode.dmr.message.filter.DmrMessageFilterSet;
|
||||
import io.github.dsheirer.module.decode.event.DecodeEvent;
|
||||
import io.github.dsheirer.module.decode.fleetsync2.Fleetsync2Decoder;
|
||||
@@ -90,6 +92,7 @@ import io.github.dsheirer.module.decode.p25.phase1.message.filter.P25P1MessageFi
|
||||
import io.github.dsheirer.module.decode.p25.phase2.DecodeConfigP25Phase2;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.P25P2DecoderHDQPSK;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.P25P2DecoderState;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.P25P2Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.filter.P25P2MessageFilterSet;
|
||||
import io.github.dsheirer.module.decode.passport.DecodeConfigPassport;
|
||||
import io.github.dsheirer.module.decode.passport.PassportDecoder;
|
||||
@@ -149,7 +152,7 @@ public class DecoderFactory
|
||||
UserPreferences userPreferences, TrafficChannelManager trafficChannelManager,
|
||||
IChannelDescriptor channelDescriptor)
|
||||
{
|
||||
List<Module> modules = new ArrayList<Module>();
|
||||
List<Module> modules = new ArrayList<>();
|
||||
|
||||
AliasList aliasList = aliasModel.getAliasList(channel.getAliasListName());
|
||||
modules.add(new AliasActionManager(aliasList));
|
||||
@@ -178,7 +181,8 @@ public class DecoderFactory
|
||||
processLTRNet(channel, modules, aliasList, (DecodeConfigLTRNet) decodeConfig);
|
||||
break;
|
||||
case MPT1327:
|
||||
processMPT1327(channelMapModel, channel, modules, aliasList, channelType, (DecodeConfigMPT1327) decodeConfig);
|
||||
processMPT1327(channelMapModel, channel, modules, aliasList, channelType,
|
||||
(DecodeConfigMPT1327) decodeConfig, userPreferences);
|
||||
break;
|
||||
case PASSPORT:
|
||||
processPassport(channel, modules, aliasList, decodeConfig);
|
||||
@@ -187,7 +191,7 @@ public class DecoderFactory
|
||||
processP25Phase1(channel, userPreferences, modules, aliasList, channelType, (DecodeConfigP25Phase1) decodeConfig);
|
||||
break;
|
||||
case P25_PHASE2:
|
||||
processP25Phase2(channel, userPreferences, modules, aliasList);
|
||||
processP25Phase2(channel, userPreferences, modules, aliasList, trafficChannelManager);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown decoder type [" + decodeConfig.getDecoderType().toString() + "]");
|
||||
@@ -202,14 +206,53 @@ public class DecoderFactory
|
||||
* @param userPreferences reference
|
||||
* @param modules collection to add to
|
||||
* @param aliasList for the channel
|
||||
* @param trafficChannelManager from parent, if this is for a traffic channel, otherwise this can be null and it
|
||||
* will be created automatically.
|
||||
*/
|
||||
private static void processP25Phase2(Channel channel, UserPreferences userPreferences, List<Module> modules, AliasList aliasList) {
|
||||
private static void processP25Phase2(Channel channel, UserPreferences userPreferences, List<Module> modules,
|
||||
AliasList aliasList, TrafficChannelManager trafficChannelManager)
|
||||
{
|
||||
|
||||
modules.add(new P25P2DecoderHDQPSK((DecodeConfigP25Phase2)channel.getDecodeConfiguration()));
|
||||
|
||||
modules.add(new P25P2DecoderState(channel, 0));
|
||||
modules.add(new P25P2DecoderState(channel, 1));
|
||||
modules.add(new P25P2AudioModule(userPreferences, 0, aliasList));
|
||||
modules.add(new P25P2AudioModule(userPreferences, 1, aliasList));
|
||||
P25TrafficChannelManager p25TrafficChannelManager = null;
|
||||
|
||||
if(channel.getChannelType() == ChannelType.STANDARD)
|
||||
{
|
||||
p25TrafficChannelManager = new P25TrafficChannelManager(channel);
|
||||
}
|
||||
else if(trafficChannelManager instanceof P25TrafficChannelManager p25)
|
||||
{
|
||||
p25TrafficChannelManager = p25;
|
||||
}
|
||||
else
|
||||
{
|
||||
p25TrafficChannelManager = new P25TrafficChannelManager(channel);
|
||||
}
|
||||
|
||||
//Only add traffic channel manager to the modules if this is the control channel
|
||||
if(channel.isStandardChannel())
|
||||
{
|
||||
modules.add(p25TrafficChannelManager);
|
||||
}
|
||||
|
||||
PatchGroupManager patchGroupManager = new PatchGroupManager();
|
||||
modules.add(new P25P2DecoderState(channel, P25P2Message.TIMESLOT_1, p25TrafficChannelManager, patchGroupManager));
|
||||
modules.add(new P25P2DecoderState(channel, P25P2Message.TIMESLOT_2, p25TrafficChannelManager, patchGroupManager));
|
||||
modules.add(new P25P2AudioModule(userPreferences, P25P2Message.TIMESLOT_1, aliasList));
|
||||
modules.add(new P25P2AudioModule(userPreferences, P25P2Message.TIMESLOT_2, aliasList));
|
||||
|
||||
|
||||
//Add a channel rotation monitor when we have multiple control channel frequencies specified
|
||||
if(channel.getSourceConfiguration() instanceof SourceConfigTunerMultipleFrequency &&
|
||||
((SourceConfigTunerMultipleFrequency)channel.getSourceConfiguration()).hasMultipleFrequencies())
|
||||
{
|
||||
List<State> activeStates = new ArrayList<>();
|
||||
activeStates.add(State.CONTROL);
|
||||
modules.add(new ChannelRotationMonitor(activeStates,
|
||||
((SourceConfigTunerMultipleFrequency)channel.getSourceConfiguration()).getFrequencyRotationDelay(),
|
||||
userPreferences));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,7 +262,8 @@ public class DecoderFactory
|
||||
* @param modules collection to add to
|
||||
* @param aliasList for the channel
|
||||
*/
|
||||
private static void processP25Phase1(Channel channel, UserPreferences userPreferences, List<Module> modules, AliasList aliasList, ChannelType channelType, DecodeConfigP25Phase1 decodeConfig) {
|
||||
private static void processP25Phase1(Channel channel, UserPreferences userPreferences, List<Module> modules, AliasList aliasList, ChannelType channelType, DecodeConfigP25Phase1 decodeConfig)
|
||||
{
|
||||
DecodeConfigP25Phase1 p25Config = decodeConfig;
|
||||
|
||||
switch(p25Config.getModulation())
|
||||
@@ -249,13 +293,12 @@ public class DecoderFactory
|
||||
modules.add(new P25P1AudioModule(userPreferences, aliasList));
|
||||
|
||||
//Add a channel rotation monitor when we have multiple control channel frequencies specified
|
||||
if(channel.getSourceConfiguration() instanceof SourceConfigTunerMultipleFrequency &&
|
||||
((SourceConfigTunerMultipleFrequency)channel.getSourceConfiguration()).hasMultipleFrequencies())
|
||||
if(channel.getSourceConfiguration() instanceof SourceConfigTunerMultipleFrequency sctmf &&
|
||||
sctmf.hasMultipleFrequencies())
|
||||
{
|
||||
List<State> activeStates = new ArrayList<>();
|
||||
activeStates.add(State.CONTROL);
|
||||
modules.add(new ChannelRotationMonitor(activeStates,
|
||||
((SourceConfigTunerMultipleFrequency)channel.getSourceConfiguration()).getFrequencyRotationDelay()));
|
||||
modules.add(new ChannelRotationMonitor(activeStates, sctmf.getFrequencyRotationDelay(), userPreferences));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +328,10 @@ public class DecoderFactory
|
||||
* @param channelType for control or traffic
|
||||
* @param decodeConfig configuration
|
||||
*/
|
||||
private static void processMPT1327(ChannelMapModel channelMapModel, Channel channel, List<Module> modules, AliasList aliasList, ChannelType channelType, DecodeConfigMPT1327 decodeConfig) {
|
||||
private static void processMPT1327(ChannelMapModel channelMapModel, Channel channel, List<Module> modules,
|
||||
AliasList aliasList, ChannelType channelType, DecodeConfigMPT1327 decodeConfig,
|
||||
UserPreferences userPreferences)
|
||||
{
|
||||
DecodeConfigMPT1327 mptConfig = decodeConfig;
|
||||
ChannelMap channelMap = channelMapModel.getChannelMap(mptConfig.getChannelMapName());
|
||||
Sync sync = mptConfig.getSync();
|
||||
@@ -317,13 +363,12 @@ public class DecoderFactory
|
||||
}
|
||||
|
||||
//Add a channel rotation monitor when we have multiple control channel frequencies specified
|
||||
if(channel.getSourceConfiguration() instanceof SourceConfigTunerMultipleFrequency &&
|
||||
((SourceConfigTunerMultipleFrequency)channel.getSourceConfiguration()).hasMultipleFrequencies())
|
||||
if(channel.getSourceConfiguration() instanceof SourceConfigTunerMultipleFrequency sctmf &&
|
||||
sctmf.hasMultipleFrequencies())
|
||||
{
|
||||
List<State> activeStates = new ArrayList<>();
|
||||
activeStates.add(State.CONTROL);
|
||||
modules.add(new ChannelRotationMonitor(activeStates,
|
||||
((SourceConfigTunerMultipleFrequency)channel.getSourceConfiguration()).getFrequencyRotationDelay()));
|
||||
modules.add(new ChannelRotationMonitor(activeStates, sctmf.getFrequencyRotationDelay(), userPreferences));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,8 +485,8 @@ public class DecoderFactory
|
||||
modules.add(dmrTrafficChannelManager);
|
||||
}
|
||||
|
||||
DMRDecoderState state1 = new DMRDecoderState(channel, 1, dmrTrafficChannelManager);
|
||||
DMRDecoderState state2 = new DMRDecoderState(channel, 2, dmrTrafficChannelManager);
|
||||
DMRDecoderState state1 = new DMRDecoderState(channel, DMRMessage.TIMESLOT_1, dmrTrafficChannelManager);
|
||||
DMRDecoderState state2 = new DMRDecoderState(channel, DMRMessage.TIMESLOT_2, dmrTrafficChannelManager);
|
||||
|
||||
//Register the states with each other so that they can pass Cap+ site status messaging to resolve current channel
|
||||
state1.setSisterDecoderState(state2);
|
||||
@@ -457,7 +502,7 @@ public class DecoderFactory
|
||||
lsn.setTimeslotFrequency(rest.getTimeslotFrequency());
|
||||
}
|
||||
|
||||
if(lsn.getTimeslot() == 1)
|
||||
if(lsn.getTimeslot() == DMRMessage.TIMESLOT_1)
|
||||
{
|
||||
state1.setCurrentChannel(lsn);
|
||||
state2.setCurrentChannel(lsn.getSisterTimeslot());
|
||||
@@ -473,7 +518,7 @@ public class DecoderFactory
|
||||
{
|
||||
DecodeEvent event = decodeConfig.getChannelGrantEvent();
|
||||
|
||||
if(decodeConfig.getChannelGrantEvent().getTimeslot() == 1)
|
||||
if(decodeConfig.getChannelGrantEvent().getTimeslot() == DMRMessage.TIMESLOT_1)
|
||||
{
|
||||
state1.setCurrentCallEvent(event);
|
||||
|
||||
@@ -495,17 +540,16 @@ public class DecoderFactory
|
||||
|
||||
modules.add(state1);
|
||||
modules.add(state2);
|
||||
modules.add(new DMRAudioModule(userPreferences, aliasList, 1));
|
||||
modules.add(new DMRAudioModule(userPreferences, aliasList, 2));
|
||||
modules.add(new DMRAudioModule(userPreferences, aliasList, DMRMessage.TIMESLOT_1));
|
||||
modules.add(new DMRAudioModule(userPreferences, aliasList, DMRMessage.TIMESLOT_2));
|
||||
|
||||
//Add a channel rotation monitor when we have multiple control channel frequencies specified
|
||||
if(channel.getSourceConfiguration() instanceof SourceConfigTunerMultipleFrequency &&
|
||||
((SourceConfigTunerMultipleFrequency)channel.getSourceConfiguration()).hasMultipleFrequencies())
|
||||
if(channel.getSourceConfiguration() instanceof SourceConfigTunerMultipleFrequency sctmf &&
|
||||
sctmf.hasMultipleFrequencies())
|
||||
{
|
||||
List<State> activeStates = new ArrayList<>();
|
||||
activeStates.add(State.CONTROL);
|
||||
modules.add(new ChannelRotationMonitor(activeStates,
|
||||
((SourceConfigTunerMultipleFrequency)channel.getSourceConfiguration()).getFrequencyRotationDelay()));
|
||||
modules.add(new ChannelRotationMonitor(activeStates, sctmf.getFrequencyRotationDelay(), userPreferences));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.config;
|
||||
|
||||
@@ -34,8 +31,7 @@ import io.github.dsheirer.module.decode.ltrnet.DecodeConfigLTRNet;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.DecodeConfigLTRStandard;
|
||||
import io.github.dsheirer.module.decode.mpt1327.DecodeConfigMPT1327;
|
||||
import io.github.dsheirer.module.decode.nbfm.DecodeConfigNBFM;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.DecodeConfigP25Phase1;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.DecodeConfigP25Phase2;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.DecodeConfigP25;
|
||||
import io.github.dsheirer.module.decode.passport.DecodeConfigPassport;
|
||||
import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
|
||||
|
||||
@@ -47,10 +43,9 @@ import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
|
||||
@JsonSubTypes.Type(value = DecodeConfigLTRStandard.class, name = "decodeConfigLTRStandard"),
|
||||
@JsonSubTypes.Type(value = DecodeConfigMPT1327.class, name = "decodeConfigMPT1327"),
|
||||
@JsonSubTypes.Type(value = DecodeConfigNBFM.class, name = "decodeConfigNBFM"),
|
||||
@JsonSubTypes.Type(value = DecodeConfigP25Phase1.class, name = "decodeConfigP25Phase1"),
|
||||
@JsonSubTypes.Type(value = DecodeConfigP25Phase2.class, name = "decodeConfigP25Phase2"),
|
||||
@JsonSubTypes.Type(value = DecodeConfigP25.class, name = "decodeConfigP25"),
|
||||
@JsonSubTypes.Type(value = DecodeConfigPassport.class, name = "decodeConfigPassport"),
|
||||
@JsonSubTypes.Type(value = DecodeConfigDMR.class, name = "decodeConfigDMR")
|
||||
@JsonSubTypes.Type(value = DecodeConfigDMR.class, name = "decodeConfigDMR")
|
||||
})
|
||||
@JacksonXmlRootElement(localName = "decode_configuration")
|
||||
public abstract class DecodeConfiguration extends Configuration
|
||||
@@ -58,10 +53,7 @@ public abstract class DecodeConfiguration extends Configuration
|
||||
public static final int DEFAULT_CALL_TIMEOUT_DELAY_SECONDS = 45;
|
||||
public static final int CALL_TIMEOUT_MINIMUM = 1;
|
||||
public static final int CALL_TIMEOUT_MAXIMUM = 180;
|
||||
|
||||
public static final int TRAFFIC_CHANNEL_LIMIT_DEFAULT = 3;
|
||||
public static final int TRAFFIC_CHANNEL_LIMIT_MINIMUM = 0;
|
||||
public static final int TRAFFIC_CHANNEL_LIMIT_MAXIMUM = 30;
|
||||
public static final int TRAFFIC_CHANNEL_LIMIT_DEFAULT = 20;
|
||||
|
||||
public DecodeConfiguration()
|
||||
{
|
||||
|
||||
@@ -124,7 +124,6 @@ public class DMRDecoderState extends TimeslotDecoderState
|
||||
private DMRNetworkConfigurationMonitor mNetworkConfigurationMonitor;
|
||||
private DMRTrafficChannelManager mTrafficChannelManager;
|
||||
private DecodeEvent mCurrentCallEvent;
|
||||
private long mCurrentFrequency;
|
||||
private boolean mIgnoreCRCChecksums;
|
||||
private DMRDecoderState mSisterDecoderState;
|
||||
|
||||
@@ -275,8 +274,7 @@ public class DMRDecoderState extends TimeslotDecoderState
|
||||
{
|
||||
super.reset();
|
||||
resetState();
|
||||
|
||||
mCurrentFrequency = 0;
|
||||
setCurrentFrequency(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,11 +345,11 @@ public class DMRDecoderState extends TimeslotDecoderState
|
||||
private void updateRestChannel(DMRChannel restChannel)
|
||||
{
|
||||
//Only respond if this is a standard/control channel (not a traffic channel).
|
||||
if(mChannel.isStandardChannel() && mCurrentFrequency > 0 &&
|
||||
if(mChannel.isStandardChannel() && getCurrentFrequency() > 0 &&
|
||||
restChannel.getDownlinkFrequency() > 0 &&
|
||||
restChannel.getDownlinkFrequency() != mCurrentFrequency && mTrafficChannelManager != null)
|
||||
restChannel.getDownlinkFrequency() != getCurrentFrequency() && mTrafficChannelManager != null)
|
||||
{
|
||||
mTrafficChannelManager.convertToTrafficChannel(mChannel, mCurrentFrequency, restChannel,
|
||||
mTrafficChannelManager.convertToTrafficChannel(mChannel, getCurrentFrequency(), restChannel,
|
||||
mNetworkConfigurationMonitor);
|
||||
}
|
||||
}
|
||||
@@ -1400,9 +1398,9 @@ public class DMRDecoderState extends TimeslotDecoderState
|
||||
Event event = (mCurrentCallEvent == null ? Event.START : Event.CONTINUATION);
|
||||
|
||||
//Create a repeater channel descriptor if we don't have one
|
||||
if(mCurrentChannel == null && mCurrentFrequency > 0)
|
||||
if(mCurrentChannel == null && getCurrentFrequency() > 0)
|
||||
{
|
||||
mCurrentChannel = new DMRAbsoluteChannel(getTimeslot(), getTimeslot(), mCurrentFrequency, 0);
|
||||
mCurrentChannel = new DMRAbsoluteChannel(getTimeslot(), getTimeslot(), getCurrentFrequency(), 0);
|
||||
}
|
||||
|
||||
if(mCurrentCallEvent == null)
|
||||
@@ -1475,11 +1473,12 @@ public class DMRDecoderState extends TimeslotDecoderState
|
||||
resetState();
|
||||
break;
|
||||
case NOTIFICATION_SOURCE_FREQUENCY:
|
||||
long previous = mCurrentFrequency;
|
||||
mCurrentFrequency = event.getFrequency();
|
||||
if(hasTrafficChannelManager())
|
||||
setCurrentFrequency(event.getFrequency());
|
||||
|
||||
//Only update the traffic channel manager if we're not a traffic channel.
|
||||
if(hasTrafficChannelManager() && mChannel.isStandardChannel())
|
||||
{
|
||||
mTrafficChannelManager.setCurrentControlFrequency(previous, mCurrentFrequency, mChannel);
|
||||
mTrafficChannelManager.setCurrentControlFrequency(getCurrentFrequency(), mChannel);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -132,13 +132,13 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I
|
||||
/**
|
||||
* Sets the current parent control channel frequency so that channel grants for the current frequency do not
|
||||
* produce an additional traffic channel allocation.
|
||||
* @param previousControlFrequency for the current control channel (to remove from allocated channels)
|
||||
* @param currentControlFrequency for current control channel (to add to allocated channels)
|
||||
* @param previous for the current control channel (to remove from allocated channels)
|
||||
* @param current for current control channel (to add to allocated channels)
|
||||
* @param channel for the current control channel
|
||||
*/
|
||||
public void setCurrentControlFrequency(long previousControlFrequency, long currentControlFrequency, Channel channel)
|
||||
public void processControlFrequencyUpdate(long previous, long current, Channel channel)
|
||||
{
|
||||
if(previousControlFrequency == currentControlFrequency)
|
||||
if(previous == current)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -147,18 +147,18 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I
|
||||
|
||||
try
|
||||
{
|
||||
Channel existing = mAllocatedChannelFrequencyMap.get(previousControlFrequency);
|
||||
Channel existing = mAllocatedChannelFrequencyMap.get(previous);
|
||||
|
||||
//Only remove the channel if it is non-null and it matches the current control channel.
|
||||
if(channel.equals(existing))
|
||||
{
|
||||
//Unlock the frequency in the channel rotation monitor
|
||||
getInterModuleEventBus().post(FrequencyLockChangeRequest.unlock(previousControlFrequency));
|
||||
mAllocatedChannelFrequencyMap.remove(previousControlFrequency);
|
||||
getInterModuleEventBus().post(FrequencyLockChangeRequest.unlock(previous));
|
||||
mAllocatedChannelFrequencyMap.remove(previous);
|
||||
}
|
||||
|
||||
mAllocatedChannelFrequencyMap.put(currentControlFrequency, channel);
|
||||
getInterModuleEventBus().post(FrequencyLockChangeRequest.lock(currentControlFrequency));
|
||||
mAllocatedChannelFrequencyMap.put(current, channel);
|
||||
getInterModuleEventBus().post(FrequencyLockChangeRequest.lock(current));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -23,6 +23,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
||||
import io.github.dsheirer.module.decode.dmr.message.DMRMessage;
|
||||
import io.github.dsheirer.module.decode.event.DecodeEvent;
|
||||
import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
|
||||
import java.util.ArrayList;
|
||||
@@ -64,10 +65,7 @@ public class DecodeConfigDMR extends DecodeConfiguration
|
||||
@Override
|
||||
public int[] getTimeslots()
|
||||
{
|
||||
int[] timeslots = new int[2];
|
||||
timeslots[0] = 1;
|
||||
timeslots[1] = 2;
|
||||
return timeslots;
|
||||
return new int[]{DMRMessage.TIMESLOT_1, DMRMessage.TIMESLOT_2};
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* 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
|
||||
@@ -28,6 +28,9 @@ import io.github.dsheirer.protocol.Protocol;
|
||||
*/
|
||||
public abstract class DMRMessage extends Message
|
||||
{
|
||||
public static final int TIMESLOT_1 = 1;
|
||||
public static final int TIMESLOT_2 = 2;
|
||||
|
||||
private CorrectedBinaryMessage mCorrectedBinaryMessage;
|
||||
private boolean mValid = true;
|
||||
private int mTimeslot;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -50,6 +50,28 @@ public class DecodeEvent implements IDecodeEvent
|
||||
mTimeStart = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or changes the decode event type.
|
||||
* @param type to set.
|
||||
*/
|
||||
public void setDecodeEventType(DecodeEventType type)
|
||||
{
|
||||
if(type == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Decode event type cannot be null");
|
||||
}
|
||||
|
||||
mDecodeEventType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a snapshot of this decode event for offline analysis
|
||||
*/
|
||||
public DecodeEventSnapshot getSnapshot()
|
||||
{
|
||||
return new DecodeEventSnapshot(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new decode event builder with the specified start timestamp.
|
||||
* @param decodeEventType for the event
|
||||
@@ -238,7 +260,8 @@ public class DecodeEvent implements IDecodeEvent
|
||||
sb.append(" IDS:").append(Joiner.on(",").join(mIdentifierCollection.getIdentifiers()));
|
||||
}
|
||||
sb.append(" DURATION:").append(getDuration());
|
||||
sb.append(" CHANNEL:").append(mChannelDescriptor);
|
||||
sb.append(" CHANNEL:").append(getChannelDescriptor());
|
||||
sb.append(" TIMESLOT:").append(getTimeslot());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.event;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provides duplicate decode event detection support
|
||||
*/
|
||||
public class DecodeEventDuplicateDetector
|
||||
{
|
||||
private static final long EVENT_MAX_AGE_MILLISECONDS = Duration.ofMinutes(1).toMillis();
|
||||
private Map<DecodeEventType,DecodeEventTracker> mTrackerMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Indicates if the event is a duplicate event.
|
||||
* @param event to check
|
||||
* @param timestamp of a current message to trigger time-based event age off.
|
||||
* @return true if the event is a duplicate.
|
||||
*/
|
||||
public synchronized boolean isDuplicate(IDecodeEvent event, long timestamp)
|
||||
{
|
||||
//Null event types and voice call event types are not tracked by this detector
|
||||
if(event.getEventType() == null || event.getEventType().isVoiceCallEvent())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!mTrackerMap.containsKey(event.getEventType()))
|
||||
{
|
||||
mTrackerMap.put(event.getEventType(), new DecodeEventTracker());
|
||||
}
|
||||
|
||||
boolean duplicate = mTrackerMap.get(event.getEventType()).isDuplicate(event);
|
||||
|
||||
for(DecodeEventTracker tracker: mTrackerMap.values())
|
||||
{
|
||||
tracker.ageOff(timestamp);
|
||||
}
|
||||
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks all decode events for a given decode event type
|
||||
*/
|
||||
private class DecodeEventTracker
|
||||
{
|
||||
private Map<String,IDecodeEvent> mDecodeEventMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Checks the event for duplicate
|
||||
* @param event to check
|
||||
* @return true if duplicate
|
||||
*/
|
||||
public boolean isDuplicate(IDecodeEvent event)
|
||||
{
|
||||
if(event.getIdentifierCollection().getToIdentifier() == null || event.getDetails() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
String key = getKey(event);
|
||||
|
||||
if(key == null || key.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(mDecodeEventMap.containsKey(key))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDecodeEventMap.put(key, event);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique event key that is a combinatio of the TO identifier value and the details of the event.
|
||||
* @param event for the key
|
||||
* @return generated key.
|
||||
*/
|
||||
private static String getKey(IDecodeEvent event)
|
||||
{
|
||||
return event.getIdentifierCollection().getToIdentifier().toString() + event.getDetails();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all decode events from the duplicate detection map that are too old.
|
||||
* @param timestamp for the current messaging.
|
||||
*/
|
||||
public void ageOff(long timestamp)
|
||||
{
|
||||
long threshold = timestamp - EVENT_MAX_AGE_MILLISECONDS;
|
||||
List<String> toRemove = new ArrayList<>();
|
||||
|
||||
for(Map.Entry<String,IDecodeEvent> entry: mDecodeEventMap.entrySet())
|
||||
{
|
||||
if(entry.getValue() == null || entry.getValue().getTimeStart() < threshold)
|
||||
{
|
||||
toRemove.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
for(String key: toRemove)
|
||||
{
|
||||
mDecodeEventMap.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -115,9 +115,9 @@ public class DecodeEventModel extends ClearableHistoryModel<IDecodeEvent> implem
|
||||
|
||||
if(channelDescriptor != null)
|
||||
{
|
||||
if(event.hasTimeslot())
|
||||
if(event.hasTimeslot() && !event.toString().contains("TS"))
|
||||
{
|
||||
return channelDescriptor + " TS:" + event.getTimeslot();
|
||||
return channelDescriptor + " TS" + event.getTimeslot();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -126,9 +126,9 @@ public class DecodeEventModel extends ClearableHistoryModel<IDecodeEvent> implem
|
||||
}
|
||||
else
|
||||
{
|
||||
if(event.hasTimeslot())
|
||||
if(event.hasTimeslot() && !event.toString().contains("TS"))
|
||||
{
|
||||
return "TS:" + event.getTimeslot();
|
||||
return "TS" + event.getTimeslot();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
|
||||
/**
|
||||
* Snapshot of a decode event that also preserves the object instance hash code.
|
||||
*/
|
||||
public class DecodeEventSnapshot extends DecodeEvent
|
||||
{
|
||||
private int mOriginalHashCode;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param decodeEvent to snapshot
|
||||
*/
|
||||
public DecodeEventSnapshot(DecodeEvent decodeEvent)
|
||||
{
|
||||
super(decodeEvent.getEventType(), decodeEvent.getTimeStart());
|
||||
mOriginalHashCode = decodeEvent.hashCode();
|
||||
setDetails(decodeEvent.getDetails());
|
||||
setDuration(decodeEvent.getDuration());
|
||||
setProtocol(decodeEvent.getProtocol());
|
||||
setTimeslot(decodeEvent.getTimeslot());
|
||||
setChannelDescriptor(decodeEvent.getChannelDescriptor());
|
||||
if(decodeEvent.getIdentifierCollection() != null)
|
||||
{
|
||||
setIdentifierCollection(new IdentifierCollection(decodeEvent.getIdentifierCollection().getIdentifiers()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashcode of the original decode event for this snapshot (not this snapshot instance's hash code).
|
||||
* @return
|
||||
*/
|
||||
public int getOriginalHashCode()
|
||||
{
|
||||
return mOriginalHashCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frequency for the channel descriptor
|
||||
* @return frequency or zero.
|
||||
*/
|
||||
public long getFrequency()
|
||||
{
|
||||
return getChannelDescriptor() != null ? getChannelDescriptor().getDownlinkFrequency() : 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -55,6 +55,7 @@ public enum DecodeEventType
|
||||
DATA_CALL_ENCRYPTED("Encrypted Data Call"),
|
||||
DATA_PACKET("Data Packet"),
|
||||
DEREGISTER("Deregister"),
|
||||
DYNAMIC_REGROUP("Dynamic Regroup"),
|
||||
EMERGENCY("EMERGENCY"),
|
||||
FUNCTION("Function"),
|
||||
GPS("GPS"),
|
||||
@@ -106,7 +107,7 @@ public enum DecodeEventType
|
||||
public static final EnumSet<DecodeEventType> COMMANDS = EnumSet.of(DecodeEventType.ANNOUNCEMENT,
|
||||
DecodeEventType.STATION_ID, DecodeEventType.ACKNOWLEDGE, DecodeEventType.PAGE, DecodeEventType.QUERY,
|
||||
DecodeEventType.RADIO_CHECK, DecodeEventType.STATUS, DecodeEventType.COMMAND, DecodeEventType.EMERGENCY,
|
||||
DecodeEventType.NOTIFICATION, DecodeEventType.FUNCTION);
|
||||
DecodeEventType.NOTIFICATION, DecodeEventType.FUNCTION, DecodeEventType.DYNAMIC_REGROUP);
|
||||
|
||||
/**
|
||||
* Data call event types for filtering
|
||||
@@ -129,6 +130,13 @@ public enum DecodeEventType
|
||||
public static final EnumSet<DecodeEventType> OTHERS = EnumSet.copyOf(Arrays.stream(DecodeEventType.values())
|
||||
.filter(decodeEventType -> !decodeEventType.isGrouped()).toList());
|
||||
|
||||
/**
|
||||
* Voice call event types.
|
||||
*/
|
||||
public static final EnumSet<DecodeEventType> VOICE_CALL_EVENTS = EnumSet.of(CALL, CALL_ENCRYPTED, CALL_GROUP,
|
||||
CALL_GROUP_ENCRYPTED, CALL_PATCH_GROUP, CALL_PATCH_GROUP_ENCRYPTED, CALL_INTERCONNECT,
|
||||
CALL_INTERCONNECT_ENCRYPTED, CALL_UNIT_TO_UNIT, CALL_UNIT_TO_UNIT_ENCRYPTED);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param label for the element
|
||||
@@ -149,12 +157,12 @@ public enum DecodeEventType
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is a call event.
|
||||
* @return true if this is a call event type.
|
||||
* Indicates if this is a voice call event.
|
||||
* @return true if this is a voice call event type.
|
||||
*/
|
||||
public boolean isCallEvent()
|
||||
public boolean isVoiceCallEvent()
|
||||
{
|
||||
return VOICE_CALLS.contains(this) || VOICE_CALLS_ENCRYPTED.contains(this) || DATA_CALLS.contains(this);
|
||||
return VOICE_CALL_EVENTS.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* 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
|
||||
@@ -37,7 +37,7 @@ public class UDPPort extends IntegerIdentifier
|
||||
*/
|
||||
public UDPPort(int value, Role role)
|
||||
{
|
||||
super(value, IdentifierClass.NETWORK, Form.UDP_PORT, role);
|
||||
super(value, IdentifierClass.USER_NETWORK_PORT, Form.UDP_PORT, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -76,6 +76,32 @@ public class MPT1327TrafficChannelManager extends TrafficChannelManager implemen
|
||||
mChannelMap = channelMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification that the control frequency is updated.
|
||||
* @param previous frequency for the control channel (to remove from allocated channels)
|
||||
* @param current frequency for the control channel (to add to allocated channels)
|
||||
* @param channel for the current control channel
|
||||
*/
|
||||
@Override
|
||||
protected void processControlFrequencyUpdate(long previous, long current, Channel channel)
|
||||
{
|
||||
MPT1327Channel toRemove = null;
|
||||
|
||||
for(MPT1327Channel mpt: mAllocatedTrafficChannelMap.keySet())
|
||||
{
|
||||
if(mpt.getDownlinkFrequency() == current)
|
||||
{
|
||||
toRemove = mpt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(toRemove != null)
|
||||
{
|
||||
broadcast(new ChannelEvent(mAllocatedTrafficChannelMap.get(toRemove), ChannelEvent.Event.REQUEST_DISABLE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes channel grants to allocate traffic channels and track overall channel usage. Generates
|
||||
* decode events for each new channel that is allocated.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package io.github.dsheirer.module.decode.p25;
|
||||
|
||||
|
||||
import io.github.dsheirer.module.decode.p25.reference.ServiceOptions;
|
||||
|
||||
/**
|
||||
* APCO25 message that exposes a service options configuration
|
||||
*/
|
||||
public interface IServiceOptionsProvider
|
||||
{
|
||||
/**
|
||||
* Service Options
|
||||
* @return service options
|
||||
*/
|
||||
ServiceOptions getServiceOptions();
|
||||
}
|
||||
@@ -117,7 +117,7 @@ public class P25ChannelGrantEvent extends P25DecodeEvent
|
||||
* Sets the channel descriptor for this event
|
||||
* @param channelDescriptor
|
||||
*/
|
||||
public P25ChannelGrantDecodeEventBuilder channel(IChannelDescriptor channelDescriptor)
|
||||
public P25ChannelGrantDecodeEventBuilder channelDescriptor(IChannelDescriptor channelDescriptor)
|
||||
{
|
||||
mChannelDescriptor = channelDescriptor;
|
||||
return this;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.github.dsheirer.module.decode.p25;
|
||||
|
||||
import io.github.dsheirer.controller.channel.event.PreloadDataContent;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBand;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Frequency bands (aka Identifier Update) to preload into a traffic channel.
|
||||
*/
|
||||
public class P25FrequencyBandPreloadDataContent extends PreloadDataContent<Collection<IFrequencyBand>>
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param data to preload
|
||||
*/
|
||||
public P25FrequencyBandPreloadDataContent(Collection<IFrequencyBand> data)
|
||||
{
|
||||
super(data);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -23,14 +23,14 @@ package io.github.dsheirer.module.decode.p25.audio;
|
||||
import io.github.dsheirer.audio.codec.mbe.MBECallSequence;
|
||||
import io.github.dsheirer.audio.codec.mbe.MBECallSequenceRecorder;
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.encryption.EncryptionKeyIdentifier;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25P1Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.hdu.HDUMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.hdu.HeaderData;
|
||||
import io.github.dsheirer.identifier.encryption.EncryptionKeyIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaPatchGroupVoiceChannelUpdate;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaPatchGroupVoiceChannelUser;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaGroupRegroupVoiceChannelUpdate;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaGroupRegroupVoiceChannelUser;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCGroupVoiceChannelUpdateExplicit;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCGroupVoiceChannelUser;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCTelephoneInterconnectVoiceChannelUser;
|
||||
@@ -86,9 +86,9 @@ public class P25P1CallSequenceRecorder extends MBECallSequenceRecorder
|
||||
@Override
|
||||
public void receive(IMessage message)
|
||||
{
|
||||
if(message instanceof P25Message)
|
||||
if(message instanceof P25P1Message)
|
||||
{
|
||||
P25Message p25 = (P25Message)message;
|
||||
P25P1Message p25 = (P25P1Message)message;
|
||||
|
||||
if(p25.isValid())
|
||||
{
|
||||
@@ -113,7 +113,7 @@ public class P25P1CallSequenceRecorder extends MBECallSequenceRecorder
|
||||
/**
|
||||
* Processes any P25 Phase 1 message
|
||||
*/
|
||||
public void process(P25Message message)
|
||||
public void process(P25P1Message message)
|
||||
{
|
||||
if(message instanceof LDUMessage)
|
||||
{
|
||||
@@ -200,15 +200,15 @@ public class P25P1CallSequenceRecorder extends MBECallSequenceRecorder
|
||||
mCallSequence.setToIdentifier(tivcu.getAddress().toString());
|
||||
mCallSequence.setCallType(CALL_TYPE_TELEPHONE_INTERCONNECT);
|
||||
break;
|
||||
case MOTOROLA_PATCH_GROUP_VOICE_CHANNEL_USER:
|
||||
LCMotorolaPatchGroupVoiceChannelUser mpgvcu = (LCMotorolaPatchGroupVoiceChannelUser)lcw;
|
||||
case MOTOROLA_GROUP_REGROUP_VOICE_CHANNEL_USER:
|
||||
LCMotorolaGroupRegroupVoiceChannelUser mpgvcu = (LCMotorolaGroupRegroupVoiceChannelUser)lcw;
|
||||
mCallSequence.setFromIdentifier(mpgvcu.getSourceAddress().toString());
|
||||
mCallSequence.setToIdentifier(mpgvcu.getGroupAddress().toString());
|
||||
mCallSequence.setToIdentifier(mpgvcu.getSupergroupAddress().toString());
|
||||
mCallSequence.setCallType(CALL_TYPE_GROUP);
|
||||
break;
|
||||
case MOTOROLA_PATCH_GROUP_VOICE_CHANNEL_UPDATE:
|
||||
LCMotorolaPatchGroupVoiceChannelUpdate mpgvcup = (LCMotorolaPatchGroupVoiceChannelUpdate)lcw;
|
||||
mCallSequence.setToIdentifier(mpgvcup.getPatchGroup().toString());
|
||||
case MOTOROLA_GROUP_REGROUP_VOICE_CHANNEL_UPDATE:
|
||||
LCMotorolaGroupRegroupVoiceChannelUpdate mpgvcup = (LCMotorolaGroupRegroupVoiceChannelUpdate)lcw;
|
||||
mCallSequence.setToIdentifier(mpgvcup.getSupergroupAddress().toString());
|
||||
mCallSequence.setCallType(CALL_TYPE_GROUP);
|
||||
break;
|
||||
case CALL_TERMINATION_OR_CANCELLATION:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* 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
|
||||
@@ -36,6 +36,8 @@ import io.github.dsheirer.identifier.tone.ToneSequence;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.IMessageProvider;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.EncryptionSynchronizationSequence;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.MacMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.MacStructure;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.PushToTalk;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.timeslot.AbstractVoiceTimeslot;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
@@ -111,10 +113,8 @@ public class P25P2AudioModule extends AmbeAudioModule implements IdentifierUpdat
|
||||
{
|
||||
if(message.getTimeslot() == getTimeslot())
|
||||
{
|
||||
if(message instanceof AbstractVoiceTimeslot)
|
||||
if(message instanceof AbstractVoiceTimeslot abstractVoiceTimeslot)
|
||||
{
|
||||
AbstractVoiceTimeslot abstractVoiceTimeslot = (AbstractVoiceTimeslot)message;
|
||||
|
||||
if(mEncryptedCallStateEstablished)
|
||||
{
|
||||
if(!mEncryptedCall)
|
||||
@@ -128,13 +128,18 @@ public class P25P2AudioModule extends AmbeAudioModule implements IdentifierUpdat
|
||||
mQueuedAudioTimeslots.offer(abstractVoiceTimeslot);
|
||||
}
|
||||
}
|
||||
else if(message instanceof PushToTalk && message.isValid())
|
||||
else if(message instanceof MacMessage macMessage && message.isValid())
|
||||
{
|
||||
mEncryptedCallStateEstablished = true;
|
||||
mEncryptedCall = ((PushToTalk)message).isEncrypted();
|
||||
MacStructure macStructure = macMessage.getMacStructure();
|
||||
|
||||
//There should not be any pending voice timeslots to process since the PTT message is the first in
|
||||
//the audio call sequence
|
||||
if(macStructure instanceof PushToTalk pushToTalk)
|
||||
{
|
||||
mEncryptedCallStateEstablished = true;
|
||||
mEncryptedCall = pushToTalk.isEncrypted();
|
||||
//There should not be any pending voice timeslots to process since the PTT message is the first in
|
||||
//the audio call sequence.
|
||||
clearPendingVoiceTimeslots();
|
||||
}
|
||||
}
|
||||
else if(message instanceof EncryptionSynchronizationSequence && message.isValid())
|
||||
{
|
||||
@@ -159,6 +164,14 @@ public class P25P2AudioModule extends AmbeAudioModule implements IdentifierUpdat
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears/deletes any pending voice timeslots
|
||||
*/
|
||||
private void clearPendingVoiceTimeslots()
|
||||
{
|
||||
mQueuedAudioTimeslots.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the audio voice frames
|
||||
* @param voiceFrames to process
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.audio;
|
||||
@@ -30,21 +27,20 @@ import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.EncryptionSynchronizationSequence;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.P25P2Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.MacMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.MacStructure;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.EndPushToTalk;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.GroupVoiceChannelUserAbbreviated;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.GroupVoiceChannelUserExtended;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.MacStructure;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.PushToTalk;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.TelephoneInterconnectVoiceChannelUser;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.UnitToUnitVoiceChannelUserAbbreviated;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.UnitToUnitVoiceChannelUserExtended;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.timeslot.AbstractVoiceTimeslot;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* P25 Phase 2 AMBE Frame recorder generates P25 call sequence recordings containing JSON representations of audio
|
||||
* frames, optional encryption and call identifiers.
|
||||
@@ -229,19 +225,19 @@ public class P25P2CallSequenceRecorder extends MBECallSequenceRecorder
|
||||
case END_PUSH_TO_TALK:
|
||||
processEndPTT(mac);
|
||||
break;
|
||||
case TDMA_1_GROUP_VOICE_CHANNEL_USER_ABBREVIATED:
|
||||
case TDMA_01_GROUP_VOICE_CHANNEL_USER_ABBREVIATED:
|
||||
processGVCUA(mac);
|
||||
break;
|
||||
case TDMA_2_UNIT_TO_UNIT_VOICE_CHANNEL_USER:
|
||||
case TDMA_02_UNIT_TO_UNIT_VOICE_CHANNEL_USER_ABBREVIATED:
|
||||
processUTUVCU(mac);
|
||||
break;
|
||||
case TDMA_3_TELEPHONE_INTERCONNECT_VOICE_CHANNEL_USER:
|
||||
case TDMA_03_TELEPHONE_INTERCONNECT_VOICE_CHANNEL_USER:
|
||||
processTIVCU(mac);
|
||||
break;
|
||||
case TDMA_33_GROUP_VOICE_CHANNEL_USER_EXTENDED:
|
||||
case TDMA_21_GROUP_VOICE_CHANNEL_USER_EXTENDED:
|
||||
processGVCUE(mac);
|
||||
break;
|
||||
case TDMA_34_UNIT_TO_UNIT_VOICE_CHANNEL_USER_EXTENDED:
|
||||
case TDMA_22_UNIT_TO_UNIT_VOICE_CHANNEL_USER_EXTENDED:
|
||||
processUTUVCUE(mac);
|
||||
break;
|
||||
}
|
||||
@@ -258,7 +254,7 @@ public class P25P2CallSequenceRecorder extends MBECallSequenceRecorder
|
||||
if(mac instanceof UnitToUnitVoiceChannelUserExtended)
|
||||
{
|
||||
UnitToUnitVoiceChannelUserExtended uuvcue = (UnitToUnitVoiceChannelUserExtended)mac;
|
||||
mCallSequence.setFromIdentifier(uuvcue.getSourceAddress().toString());
|
||||
mCallSequence.setFromIdentifier(uuvcue.getSource().toString());
|
||||
mCallSequence.setToIdentifier(uuvcue.getTargetAddress().toString());
|
||||
mCallSequence.setCallType(CALL_TYPE_INDIVIDUAL);
|
||||
if(uuvcue.getServiceOptions().isEncrypted())
|
||||
@@ -276,7 +272,7 @@ public class P25P2CallSequenceRecorder extends MBECallSequenceRecorder
|
||||
if(mac instanceof GroupVoiceChannelUserExtended)
|
||||
{
|
||||
GroupVoiceChannelUserExtended gvcue = (GroupVoiceChannelUserExtended)mac;
|
||||
mCallSequence.setFromIdentifier(gvcue.getSourceAddress().toString());
|
||||
mCallSequence.setFromIdentifier(gvcue.getSource().toString());
|
||||
mCallSequence.setToIdentifier(gvcue.getGroupAddress().toString());
|
||||
mCallSequence.setCallType(CALL_TYPE_GROUP);
|
||||
if(gvcue.getServiceOptions().isEncrypted())
|
||||
@@ -294,7 +290,7 @@ public class P25P2CallSequenceRecorder extends MBECallSequenceRecorder
|
||||
if(mac instanceof TelephoneInterconnectVoiceChannelUser)
|
||||
{
|
||||
TelephoneInterconnectVoiceChannelUser tivcu = (TelephoneInterconnectVoiceChannelUser)mac;
|
||||
mCallSequence.setToIdentifier(tivcu.getToOrFromAddress().toString());
|
||||
mCallSequence.setToIdentifier(tivcu.getTargetAddress().toString());
|
||||
mCallSequence.setCallType(CALL_TYPE_TELEPHONE_INTERCONNECT);
|
||||
if(tivcu.getServiceOptions().isEncrypted())
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -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.p25.identifier;
|
||||
|
||||
@@ -46,4 +45,10 @@ public class APCO25Lra extends IntegerIdentifier
|
||||
{
|
||||
return new APCO25Lra(lra);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getValue() + "/x" + String.format("%02X", getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -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.p25.identifier;
|
||||
|
||||
@@ -52,4 +51,10 @@ public class APCO25Nac extends IntegerIdentifier
|
||||
{
|
||||
return new APCO25Nac(nac);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getValue() + "/x" + String.format("%03X", getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -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.p25.identifier;
|
||||
|
||||
@@ -46,4 +45,10 @@ public class APCO25Rfss extends IntegerIdentifier
|
||||
{
|
||||
return new APCO25Rfss(rfss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getValue() + "/x" + String.format("%02X", getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -15,12 +14,11 @@
|
||||
*
|
||||
* 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.identifier;
|
||||
|
||||
import io.github.dsheirer.identifier.Form;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.IdentifierClass;
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.integer.IntegerIdentifier;
|
||||
@@ -42,8 +40,14 @@ public class APCO25Site extends IntegerIdentifier
|
||||
/**
|
||||
* Creates a new APCO-25 site identifier
|
||||
*/
|
||||
public static Identifier create(int site)
|
||||
public static IntegerIdentifier create(int site)
|
||||
{
|
||||
return new APCO25Site(site);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getValue() + "/x" + String.format("%02X", getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -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.p25.identifier;
|
||||
|
||||
@@ -45,4 +44,11 @@ public class APCO25System extends IntegerIdentifier
|
||||
{
|
||||
return new APCO25System(system);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getValue() + "/x" + String.format("%03X", getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -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.p25.identifier;
|
||||
|
||||
@@ -46,4 +45,11 @@ public class APCO25Wacn extends IntegerIdentifier
|
||||
{
|
||||
return new APCO25Wacn(wacn);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getValue() + "/x" + String.format("%05X", getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.identifier.channel;
|
||||
@@ -25,7 +22,6 @@ package io.github.dsheirer.module.decode.p25.identifier.channel;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBand;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class P25Channel implements IChannelDescriptor
|
||||
@@ -151,17 +147,24 @@ public class P25Channel implements IChannelDescriptor
|
||||
}
|
||||
|
||||
/**
|
||||
* Timeslot for a TDMA channel
|
||||
* @return timeslot or 0 if the channel is not a TDMA channel
|
||||
* Timeslot for a TDMA channel, 1 or 2
|
||||
*
|
||||
* Note: the ICD uses Logical Channel 0 (LCH 0) and Logical Channel 1 (LCH 1) but we refer to them as TS1 and TS2
|
||||
* so that timeslot 0 can be used for non timeslot signalling like Sync Loss messages.
|
||||
*
|
||||
* @return timeslot or 1 if the channel is not a TDMA channel
|
||||
*/
|
||||
public int getTimeslot()
|
||||
{
|
||||
if(isTDMAChannel())
|
||||
{
|
||||
return getDownlinkChannelNumber() % getTimeslotCount();
|
||||
if(getDownlinkChannelNumber() % getTimeslotCount() == 1)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.identifier.channel;
|
||||
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBand;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/**
|
||||
@@ -11,7 +29,7 @@ import java.text.DecimalFormat;
|
||||
*/
|
||||
public class StandardChannel implements IChannelDescriptor
|
||||
{
|
||||
private static final DecimalFormat FREQUENCY_FORMATTER = new DecimalFormat("0.000");
|
||||
private static final DecimalFormat FREQUENCY_FORMATTER = new DecimalFormat("0.0000");
|
||||
private long mFrequency;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -15,12 +14,13 @@
|
||||
*
|
||||
* 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.identifier.patch;
|
||||
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroupIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
@@ -43,4 +43,9 @@ public class APCO25PatchGroup extends PatchGroupIdentifier
|
||||
{
|
||||
return new APCO25PatchGroup(patchGroup);
|
||||
}
|
||||
|
||||
public static APCO25PatchGroup create(int supergroup)
|
||||
{
|
||||
return new APCO25PatchGroup(new PatchGroup(APCO25Talkgroup.create(supergroup)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.identifier.radio;
|
||||
@@ -31,9 +28,17 @@ import io.github.dsheirer.protocol.Protocol;
|
||||
*/
|
||||
public class APCO25FullyQualifiedRadioIdentifier extends FullyQualifiedRadioIdentifier
|
||||
{
|
||||
public APCO25FullyQualifiedRadioIdentifier(int wacn, int system, int id, Role role)
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param localAddress radio identifier. This can be the same as the radio ID when the fully qualified radio
|
||||
* is not being aliased on a local radio system.
|
||||
* @param wacn of the home network for the radio.
|
||||
* @param system of the home network for the radio.
|
||||
* @param id of the radio within the home network.
|
||||
*/
|
||||
public APCO25FullyQualifiedRadioIdentifier(int localAddress, int wacn, int system, int id, Role role)
|
||||
{
|
||||
super(wacn, system, id, role);
|
||||
super(localAddress, wacn, system, id, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,13 +47,31 @@ public class APCO25FullyQualifiedRadioIdentifier extends FullyQualifiedRadioIden
|
||||
return Protocol.APCO25;
|
||||
}
|
||||
|
||||
public static APCO25FullyQualifiedRadioIdentifier createFrom(int wacn, int system, int id)
|
||||
/**
|
||||
* Creates a fully qualified radio and assigns the FROM role.
|
||||
* @param localAddress radio identifier. This can be the same as the radio ID when the fully qualified radio
|
||||
* is not being aliased on a local radio system.
|
||||
* @param wacn of the home network for the radio.
|
||||
* @param system of the home network for the radio.
|
||||
* @param id of the radio within the home network.
|
||||
* @return identifier
|
||||
*/
|
||||
public static APCO25FullyQualifiedRadioIdentifier createFrom(int localAddress, int wacn, int system, int id)
|
||||
{
|
||||
return new APCO25FullyQualifiedRadioIdentifier(wacn, system, id, Role.FROM);
|
||||
return new APCO25FullyQualifiedRadioIdentifier(localAddress, wacn, system, id, Role.FROM);
|
||||
}
|
||||
|
||||
public static APCO25FullyQualifiedRadioIdentifier createTo(int wacn, int system, int id)
|
||||
/**
|
||||
* Creates a fully qualified radio and assigns the TO role.
|
||||
* @param localAddress radio identifier. This can be the same as the radio ID when the fully qualified radio
|
||||
* is not being aliased on a local radio system.
|
||||
* @param wacn of the home network for the radio.
|
||||
* @param system of the home network for the radio.
|
||||
* @param id of the radio within the home network.
|
||||
* @return identifier
|
||||
*/
|
||||
public static APCO25FullyQualifiedRadioIdentifier createTo(int localAddress, int wacn, int system, int id)
|
||||
{
|
||||
return new APCO25FullyQualifiedRadioIdentifier(wacn, system, id, Role.TO);
|
||||
return new APCO25FullyQualifiedRadioIdentifier(localAddress, wacn, system, id, Role.TO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.identifier.talkgroup;
|
||||
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.radio.RadioIdentifier;
|
||||
import io.github.dsheirer.identifier.talkgroup.FullyQualifiedTalkgroupIdentifier;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25FullyQualifiedRadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
@@ -31,9 +32,17 @@ import io.github.dsheirer.protocol.Protocol;
|
||||
*/
|
||||
public class APCO25FullyQualifiedTalkgroupIdentifier extends FullyQualifiedTalkgroupIdentifier
|
||||
{
|
||||
public APCO25FullyQualifiedTalkgroupIdentifier(int wacn, int system, int id, Role role)
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param groupAddress used on the local system as an alias to the fully qualified talkgroup.
|
||||
* @param wacn for the talkgroup home system.
|
||||
* @param system for the talkgroup home system.
|
||||
* @param id for the talkgroup within the home system.
|
||||
* @param role played by the talkgroup.
|
||||
*/
|
||||
public APCO25FullyQualifiedTalkgroupIdentifier(int groupAddress, int wacn, int system, int id, Role role)
|
||||
{
|
||||
super(wacn, system, id, role);
|
||||
super(groupAddress, wacn, system, id, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,18 +51,39 @@ public class APCO25FullyQualifiedTalkgroupIdentifier extends FullyQualifiedTalkg
|
||||
return Protocol.APCO25;
|
||||
}
|
||||
|
||||
public static APCO25FullyQualifiedTalkgroupIdentifier createFrom(int wacn, int system, int id)
|
||||
/**
|
||||
* Creates an identifier for the fully qualified talkgroup ising the FROM role.
|
||||
* @param groupAddress used on the local system as an alias to the fully qualified talkgroup.
|
||||
* @param wacn for the talkgroup home system.
|
||||
* @param system for the talkgroup home system.
|
||||
* @param id for the talkgroup within the home system.
|
||||
*/
|
||||
public static APCO25FullyQualifiedTalkgroupIdentifier createFrom(int groupAddress, int wacn, int system, int id)
|
||||
{
|
||||
return new APCO25FullyQualifiedTalkgroupIdentifier(wacn, system, id, Role.FROM);
|
||||
return new APCO25FullyQualifiedTalkgroupIdentifier(groupAddress, wacn, system, id, Role.FROM);
|
||||
}
|
||||
|
||||
public static APCO25FullyQualifiedTalkgroupIdentifier createTo(int wacn, int system, int id)
|
||||
/**
|
||||
* Creates an identifier for the fully qualified talkgroup ising the TO role.
|
||||
* @param groupAddress used on the local system as an alias to the fully qualified talkgroup.
|
||||
* @param wacn for the talkgroup home system.
|
||||
* @param system for the talkgroup home system.
|
||||
* @param id for the talkgroup within the home system.
|
||||
*/
|
||||
public static APCO25FullyQualifiedTalkgroupIdentifier createTo(int groupAddress, int wacn, int system, int id)
|
||||
{
|
||||
return new APCO25FullyQualifiedTalkgroupIdentifier(wacn, system, id, Role.TO);
|
||||
return new APCO25FullyQualifiedTalkgroupIdentifier(groupAddress, wacn, system, id, Role.TO);
|
||||
}
|
||||
|
||||
public static APCO25FullyQualifiedTalkgroupIdentifier createAny(int wacn, int system, int id)
|
||||
/**
|
||||
* Creates an identifier for the fully qualified talkgroup ising the ANY role.
|
||||
* @param groupAddress used on the local system as an alias to the fully qualified talkgroup.
|
||||
* @param wacn for the talkgroup home system.
|
||||
* @param system for the talkgroup home system.
|
||||
* @param id for the talkgroup within the home system.
|
||||
*/
|
||||
public static APCO25FullyQualifiedTalkgroupIdentifier createAny(int groupAddress, int wacn, int system, int id)
|
||||
{
|
||||
return new APCO25FullyQualifiedTalkgroupIdentifier(wacn, system, id, Role.ANY);
|
||||
return new APCO25FullyQualifiedTalkgroupIdentifier(groupAddress, wacn, system, id, Role.ANY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.DecodeConfigP25Phase2;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = DecodeConfigP25Phase1.class, name = "decodeConfigP25Phase1"),
|
||||
@JsonSubTypes.Type(value = DecodeConfigP25Phase2.class, name = "decodeConfigP25Phase2"),
|
||||
})
|
||||
public abstract class DecodeConfigP25 extends DecodeConfiguration
|
||||
{
|
||||
private int mTrafficChannelPoolSize = TRAFFIC_CHANNEL_LIMIT_DEFAULT;
|
||||
private boolean mIgnoreDataCalls = false;
|
||||
|
||||
public DecodeConfigP25()
|
||||
{
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "ignore_data_calls")
|
||||
public boolean getIgnoreDataCalls()
|
||||
{
|
||||
return mIgnoreDataCalls;
|
||||
}
|
||||
|
||||
public void setIgnoreDataCalls(boolean ignore)
|
||||
{
|
||||
mIgnoreDataCalls = ignore;
|
||||
}
|
||||
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "traffic_channel_pool_size")
|
||||
public int getTrafficChannelPoolSize()
|
||||
{
|
||||
return mTrafficChannelPoolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the traffic channel pool size which is the maximum number of
|
||||
* simultaneous traffic channels that can be allocated.
|
||||
*
|
||||
* This limits the maximum calls so that busy systems won't cause more
|
||||
* traffic channels to be allocated than the decoder/software/host computer
|
||||
* can support.
|
||||
*/
|
||||
public void setTrafficChannelPoolSize(int size)
|
||||
{
|
||||
mTrafficChannelPoolSize = size;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1;
|
||||
|
||||
@@ -25,10 +22,12 @@ package io.github.dsheirer.module.decode.p25.phase1;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
|
||||
|
||||
public class DecodeConfigP25Phase1 extends DecodeConfiguration
|
||||
/**
|
||||
* APCO25 Phase 1 decoder configuration
|
||||
*/
|
||||
public class DecodeConfigP25Phase1 extends DecodeConfigP25
|
||||
{
|
||||
public static final int CHANNEL_ROTATION_DELAY_MINIMUM_MS = 400;
|
||||
public static final int CHANNEL_ROTATION_DELAY_DEFAULT_MS = 500;
|
||||
@@ -36,9 +35,9 @@ public class DecodeConfigP25Phase1 extends DecodeConfiguration
|
||||
|
||||
private P25P1Decoder.Modulation mModulation = P25P1Decoder.Modulation.C4FM;
|
||||
|
||||
private int mTrafficChannelPoolSize = TRAFFIC_CHANNEL_LIMIT_DEFAULT;
|
||||
private boolean mIgnoreDataCalls = false;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public DecodeConfigP25Phase1()
|
||||
{
|
||||
}
|
||||
@@ -60,37 +59,6 @@ public class DecodeConfigP25Phase1 extends DecodeConfiguration
|
||||
mModulation = modulation;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "ignore_data_calls")
|
||||
public boolean getIgnoreDataCalls()
|
||||
{
|
||||
return mIgnoreDataCalls;
|
||||
}
|
||||
|
||||
public void setIgnoreDataCalls(boolean ignore)
|
||||
{
|
||||
mIgnoreDataCalls = ignore;
|
||||
}
|
||||
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "traffic_channel_pool_size")
|
||||
public int getTrafficChannelPoolSize()
|
||||
{
|
||||
return mTrafficChannelPoolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the traffic channel pool size which is the maximum number of
|
||||
* simultaneous traffic channels that can be allocated.
|
||||
*
|
||||
* This limits the maximum calls so that busy systems won't cause more
|
||||
* traffic channels to be allocated than the decoder/software/host computer
|
||||
* can support.
|
||||
*/
|
||||
public void setTrafficChannelPoolSize(int size)
|
||||
{
|
||||
mTrafficChannelPoolSize = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source channel specification for this decoder
|
||||
*/
|
||||
|
||||
@@ -18,11 +18,16 @@
|
||||
*/
|
||||
package io.github.dsheirer.module.decode.p25.phase1;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import io.github.dsheirer.dsp.squelch.PowerMonitor;
|
||||
import io.github.dsheirer.dsp.symbol.Dibit;
|
||||
import io.github.dsheirer.dsp.symbol.DibitToByteBufferAssembler;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroupIdentifier;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.FeedbackDecoder;
|
||||
import io.github.dsheirer.module.decode.p25.P25FrequencyBandPreloadDataContent;
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.IByteBufferProvider;
|
||||
@@ -52,6 +57,18 @@ public abstract class P25P1Decoder extends FeedbackDecoder implements ISourceEve
|
||||
getDibitBroadcaster().addListener(mByteBufferAssembler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads P25 frequency bands when this is a traffic channel, since they are not transmitted on the traffic
|
||||
* channel and the decoder state needs accurate frequency values to pass to the traffic channel manager for
|
||||
* call event tracking.
|
||||
* @param preLoadDataContent with known frequency bands.
|
||||
*/
|
||||
@Subscribe
|
||||
public void process(P25FrequencyBandPreloadDataContent preLoadDataContent)
|
||||
{
|
||||
mMessageProcessor.preload(preLoadDataContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceEventListener(Listener<SourceEvent> listener )
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -30,7 +30,6 @@ import io.github.dsheirer.dsp.psk.pll.IPhaseLockedLoop;
|
||||
import io.github.dsheirer.dsp.symbol.Dibit;
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.MessageProviderModule;
|
||||
import io.github.dsheirer.message.StuffBitsMessage;
|
||||
import io.github.dsheirer.message.SyncLossMessage;
|
||||
@@ -40,8 +39,8 @@ import io.github.dsheirer.module.decode.ip.ipv4.IPV4Packet;
|
||||
import io.github.dsheirer.module.decode.ip.mototrbo.lrrp.LRRPPacket;
|
||||
import io.github.dsheirer.module.decode.ip.udp.UDPPacket;
|
||||
import io.github.dsheirer.module.decode.p25.audio.P25P1AudioModule;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25MessageFactory;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25P1Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.pdu.PDUMessageFactory;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.pdu.PDUSequence;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.pdu.packet.PacketMessage;
|
||||
@@ -73,7 +72,7 @@ public class P25P1MessageFramer implements Listener<Dibit>, IP25P1DataUnitDetect
|
||||
|
||||
private P25P1DataUnitDetector mDataUnitDetector;
|
||||
private P25P1ChannelStatusProcessor mChannelStatusProcessor = new P25P1ChannelStatusProcessor();
|
||||
private Listener<Message> mMessageListener;
|
||||
private Listener<IMessage> mMessageListener;
|
||||
private boolean mAssemblingMessage = false;
|
||||
private CorrectedBinaryMessage mBinaryMessage;
|
||||
private P25P1DataUnitID mDataUnitID;
|
||||
@@ -153,7 +152,7 @@ public class P25P1MessageFramer implements Listener<Dibit>, IP25P1DataUnitDetect
|
||||
*
|
||||
* @param messageListener to receive framed and decoded messages
|
||||
*/
|
||||
public void setListener(Listener<Message> messageListener)
|
||||
public void setListener(Listener<IMessage> messageListener)
|
||||
{
|
||||
mMessageListener = messageListener;
|
||||
}
|
||||
@@ -346,7 +345,7 @@ public class P25P1MessageFramer implements Listener<Dibit>, IP25P1DataUnitDetect
|
||||
}
|
||||
break;
|
||||
default:
|
||||
P25Message message = P25MessageFactory.create(mDataUnitID, mNAC, getTimestamp(), mBinaryMessage);
|
||||
P25P1Message message = P25MessageFactory.create(mDataUnitID, mNAC, getTimestamp(), mBinaryMessage);
|
||||
mMessageListener.receive(message);
|
||||
reset(mDataUnitID.getMessageLength());
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* 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
|
||||
@@ -20,44 +20,81 @@ package io.github.dsheirer.module.decode.p25.phase1;
|
||||
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.module.decode.p25.P25FrequencyBandPreloadDataContent;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBand;
|
||||
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.standard.LCSourceIDExtension;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.ldu.LDU1Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tdu.TDULinkControlMessage;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class P25P1MessageProcessor implements Listener<Message>
|
||||
/**
|
||||
* APCO25 Phase 1 Message Processor.
|
||||
*
|
||||
* Performs post-message creation processing before the message is sent downstream.
|
||||
*/
|
||||
public class P25P1MessageProcessor implements Listener<IMessage>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(P25P1MessageProcessor.class);
|
||||
|
||||
/**
|
||||
* Downstream message listener
|
||||
*/
|
||||
private Listener<IMessage> mMessageListener;
|
||||
|
||||
/* Map of up to 16 band identifiers per RFSS. These identifier update
|
||||
* messages are inserted into any message that conveys channel information
|
||||
* so that the uplink/downlink frequencies can be calculated */
|
||||
/**
|
||||
* Map of up to 16 band identifiers per RFSS. These identifier update messages are inserted into any message that
|
||||
* conveys channel information so that the uplink/downlink frequencies can be calculated
|
||||
*/
|
||||
private Map<Integer,IFrequencyBand> mFrequencyBandMap = new TreeMap<Integer,IFrequencyBand>();
|
||||
|
||||
/**
|
||||
* Temporary holding of an extended source link control message while it awaits the extension message to arrive.
|
||||
*/
|
||||
private ExtendedSourceLinkControlWord mExtendedSourceLinkControlWord;
|
||||
|
||||
public P25P1MessageProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Message message)
|
||||
/**
|
||||
* Preloads frequency band information from the control channel.
|
||||
* @param content to preload
|
||||
*/
|
||||
public void preload(P25FrequencyBandPreloadDataContent content)
|
||||
{
|
||||
if(content.hasData())
|
||||
{
|
||||
for(IFrequencyBand frequencyBand: content.getData())
|
||||
{
|
||||
mFrequencyBandMap.put(frequencyBand.getIdentifier(), frequencyBand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(IMessage message)
|
||||
{
|
||||
/**
|
||||
* Capture frequency band identifier messages and inject them into any
|
||||
* messages that require band information in order to calculate the
|
||||
* up-link and down-link frequencies for any numeric channel references
|
||||
* contained within the message.
|
||||
*/
|
||||
if(message.isValid())
|
||||
{
|
||||
/* Insert frequency band identifier update messages into channel-type messages */
|
||||
//Reassemble extended source link control messages.
|
||||
if(message instanceof LDU1Message ldu)
|
||||
{
|
||||
reassembleLC(ldu.getLinkControlWord());
|
||||
}
|
||||
else if(message instanceof TDULinkControlMessage tdu)
|
||||
{
|
||||
reassembleLC(tdu.getLinkControlWord());
|
||||
}
|
||||
|
||||
//Insert frequency band identifier update messages into channel-type messages */
|
||||
if(message instanceof IFrequencyBandReceiver)
|
||||
{
|
||||
IFrequencyBandReceiver receiver = (IFrequencyBandReceiver)message;
|
||||
@@ -78,8 +115,7 @@ public class P25P1MessageProcessor implements Listener<Message>
|
||||
}
|
||||
}
|
||||
|
||||
/* Store band identifiers so that they can be injected into channel
|
||||
* type messages */
|
||||
//Store band identifiers so that they can be injected into channel type messages
|
||||
if(message instanceof IFrequencyBand)
|
||||
{
|
||||
IFrequencyBand bandIdentifier = (IFrequencyBand)message;
|
||||
@@ -93,6 +129,30 @@ public class P25P1MessageProcessor implements Listener<Message>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes link control words to reassemble source ID extension messages.
|
||||
* @param linkControlWord to process
|
||||
*/
|
||||
private void reassembleLC(LinkControlWord linkControlWord)
|
||||
{
|
||||
if(linkControlWord instanceof ExtendedSourceLinkControlWord eslcw)
|
||||
{
|
||||
mExtendedSourceLinkControlWord = eslcw;
|
||||
}
|
||||
else if(linkControlWord instanceof LCSourceIDExtension sie && mExtendedSourceLinkControlWord != null)
|
||||
{
|
||||
mExtendedSourceLinkControlWord.setSourceIDExtension(sie);
|
||||
mExtendedSourceLinkControlWord = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
//The source extension message should always immediately follow the message that is being extended, so if
|
||||
//we get a message that is not an extended message or the extension, then we've missed the extension and we
|
||||
//should nullify any extended message that's waiting for the extension.
|
||||
mExtendedSourceLinkControlWord = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mFrequencyBandMap.clear();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* 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
|
||||
@@ -45,16 +45,15 @@ import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.standard.osp.SND
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.standard.osp.SecondaryControlChannelBroadcast;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.standard.osp.SecondaryControlChannelBroadcastExplicit;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.standard.osp.SystemServiceBroadcast;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Tracks the network configuration details of a P25 Phase 1 network from the broadcast messages
|
||||
@@ -236,7 +235,7 @@ public class P25P1NetworkConfigurationMonitor
|
||||
}
|
||||
break;
|
||||
case CHANNEL_IDENTIFIER_UPDATE:
|
||||
case CHANNEL_IDENTIFIER_UPDATE_EXPLICIT:
|
||||
case CHANNEL_IDENTIFIER_UPDATE_VU:
|
||||
if(lcw instanceof IFrequencyBand)
|
||||
{
|
||||
IFrequencyBand band = (IFrequencyBand)lcw;
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message;
|
||||
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
|
||||
/**
|
||||
* Utility class to declare a frequency band
|
||||
*/
|
||||
public class P25FrequencyBand implements IFrequencyBand
|
||||
{
|
||||
private int mIdentifier;
|
||||
private long mBaseFrequency;
|
||||
private long mTransmitOffset;
|
||||
private long mChannelSpacing;
|
||||
private int mBandwidth;
|
||||
private int mTimeslotCount;
|
||||
|
||||
/**
|
||||
* Construct an instance
|
||||
* @param identifier for this frequency band
|
||||
* @param baseFrequency in Hertz
|
||||
* @param transmitOffset in Hertz
|
||||
* @param channelSpacing in Hertz
|
||||
* @param bandwidth in Hertz
|
||||
* @param timeslotCount for number of timeslots, 1 or 2
|
||||
*/
|
||||
public P25FrequencyBand(int identifier, long baseFrequency, long transmitOffset, long channelSpacing,
|
||||
int bandwidth, int timeslotCount)
|
||||
{
|
||||
mIdentifier = identifier;
|
||||
mChannelSpacing = channelSpacing;
|
||||
mBaseFrequency = baseFrequency;
|
||||
mBandwidth = bandwidth;
|
||||
mTransmitOffset = transmitOffset;
|
||||
mTimeslotCount = timeslotCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mIdentifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChannelSpacing()
|
||||
{
|
||||
return mChannelSpacing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBaseFrequency()
|
||||
{
|
||||
return mBaseFrequency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBandwidth()
|
||||
{
|
||||
return mBandwidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTransmitOffset()
|
||||
{
|
||||
return mTransmitOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDownlinkFrequency(int channelNumber)
|
||||
{
|
||||
if(isTDMA())
|
||||
{
|
||||
return getBaseFrequency() + (getChannelSpacing() * (int)(FastMath.floor(channelNumber / getTimeslotCount())));
|
||||
}
|
||||
|
||||
return getBaseFrequency() + (getChannelSpacing() * channelNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUplinkFrequency(int channelNumber)
|
||||
{
|
||||
return getDownlinkFrequency(channelNumber) + getTransmitOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTDMA()
|
||||
{
|
||||
return getTimeslotCount() > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeslotCount()
|
||||
{
|
||||
return mTimeslotCount;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* 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
|
||||
@@ -49,7 +49,7 @@ public class P25MessageFactory
|
||||
* correction
|
||||
* @return constructed message parser
|
||||
*/
|
||||
public static P25Message create(P25P1DataUnitID dataUnitID, int nac, long timestamp, CorrectedBinaryMessage message)
|
||||
public static P25P1Message create(P25P1DataUnitID dataUnitID, int nac, long timestamp, CorrectedBinaryMessage message)
|
||||
{
|
||||
switch(dataUnitID)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* 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
|
||||
@@ -20,25 +20,32 @@ package io.github.dsheirer.module.decode.p25.phase1.message;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.TimeslotMessage;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25Nac;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.P25P1DataUnitID;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
public abstract class P25Message extends Message
|
||||
/**
|
||||
* Base APCO25 Phase 1 Message
|
||||
*/
|
||||
public abstract class P25P1Message extends TimeslotMessage implements IMessage
|
||||
{
|
||||
public enum DuplexMode
|
||||
{
|
||||
HALF, FULL
|
||||
}
|
||||
//P25 Phase 1 ICD defines octets starting at zero.
|
||||
public static final int OCTET_0_BIT_0 = 0;
|
||||
public static final int OCTET_1_BIT_8 = 8;
|
||||
public static final int OCTET_2_BIT_16 = 16;
|
||||
public static final int OCTET_3_BIT_24 = 24;
|
||||
public static final int OCTET_4_BIT_32 = 32;
|
||||
public static final int OCTET_5_BIT_40 = 40;
|
||||
public static final int OCTET_6_BIT_48 = 48;
|
||||
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 enum SessionMode
|
||||
{
|
||||
PACKET, CIRCUIT
|
||||
}
|
||||
|
||||
private CorrectedBinaryMessage mMessage;
|
||||
private boolean mValid = true;
|
||||
private Identifier mNAC;
|
||||
|
||||
/**
|
||||
@@ -48,10 +55,9 @@ public abstract class P25Message extends Message
|
||||
* @param nac Network Access Code (NAC) for the message
|
||||
* @param timestamp when the message was transmitted
|
||||
*/
|
||||
public P25Message(CorrectedBinaryMessage message, int nac, long timestamp)
|
||||
public P25P1Message(CorrectedBinaryMessage message, int nac, long timestamp)
|
||||
{
|
||||
super(timestamp);
|
||||
mMessage = message;
|
||||
super(message, 0, timestamp);
|
||||
mNAC = APCO25Nac.create(nac);
|
||||
}
|
||||
|
||||
@@ -61,7 +67,7 @@ public abstract class P25Message extends Message
|
||||
* @param message containing the binary message and optional corrected bit count
|
||||
* @param nac Network Access Code (NAC) for the message
|
||||
*/
|
||||
public P25Message(CorrectedBinaryMessage message, int nac)
|
||||
public P25P1Message(CorrectedBinaryMessage message, int nac)
|
||||
{
|
||||
this(message, nac, System.currentTimeMillis());
|
||||
}
|
||||
@@ -71,28 +77,15 @@ public abstract class P25Message extends Message
|
||||
* @param nac Network Access Code (NAC) for the message
|
||||
* @param timestamp when the message was transmitted
|
||||
*/
|
||||
protected P25Message(int nac, long timestamp)
|
||||
protected P25P1Message(int nac, long timestamp)
|
||||
{
|
||||
super(timestamp);
|
||||
super(null, 0, timestamp);
|
||||
mNAC = APCO25Nac.create(nac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the message binary sequence.
|
||||
* NAC code for this message
|
||||
*/
|
||||
protected void setMessage(CorrectedBinaryMessage message)
|
||||
{
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* The transmitted binary message
|
||||
*/
|
||||
public CorrectedBinaryMessage getMessage()
|
||||
{
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
public Identifier getNAC()
|
||||
{
|
||||
return mNAC;
|
||||
@@ -125,21 +118,4 @@ public abstract class P25Message extends Message
|
||||
{
|
||||
return Protocol.APCO25;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this message is valid and has passed all error detection and correction routines.
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return mValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this message to the valid/invalid state. The default state is valid (true).
|
||||
*/
|
||||
protected void setValid(boolean valid)
|
||||
{
|
||||
mValid = valid;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -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.p25.phase1.message;
|
||||
@@ -23,20 +22,19 @@ package io.github.dsheirer.module.decode.p25.phase1.message;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.P25P1DataUnitID;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* P25 Message with unknown or unrecognized data unit id
|
||||
*/
|
||||
public class UnknownP25Message extends P25Message
|
||||
public class UnknownP25Message extends P25P1Message
|
||||
{
|
||||
private P25P1DataUnitID mDataUnitID;
|
||||
|
||||
public UnknownP25Message(CorrectedBinaryMessage message, int nac, long timestamp, P25P1DataUnitID dataUnitID)
|
||||
{
|
||||
super(message, nac);
|
||||
super(message, nac, timestamp);
|
||||
mDataUnitID = dataUnitID;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -22,7 +22,7 @@ package io.github.dsheirer.module.decode.p25.phase1.message.filter;
|
||||
import io.github.dsheirer.filter.Filter;
|
||||
import io.github.dsheirer.filter.FilterElement;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25P1Message;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
@@ -51,7 +51,7 @@ public class P25OtherMessageFilter extends Filter<IMessage,String>
|
||||
@Override
|
||||
public boolean canProcess(IMessage message)
|
||||
{
|
||||
return message instanceof P25Message && super.canProcess(message);
|
||||
return message instanceof P25P1Message && super.canProcess(message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,7 +62,7 @@ public class P25OtherMessageFilter extends Filter<IMessage,String>
|
||||
@Override
|
||||
public String apply(IMessage message)
|
||||
{
|
||||
if(message instanceof P25Message)
|
||||
if(message instanceof P25P1Message)
|
||||
{
|
||||
return OTHER_KEY;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -23,7 +23,7 @@ import io.github.dsheirer.filter.FilterSet;
|
||||
import io.github.dsheirer.filter.SyncLossMessageFilter;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.SyncLossMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25P1Message;
|
||||
|
||||
/**
|
||||
* Filter set for P25 messages
|
||||
@@ -53,6 +53,6 @@ public class P25P1MessageFilterSet extends FilterSet<IMessage>
|
||||
@Override
|
||||
public boolean canProcess(IMessage message)
|
||||
{
|
||||
return message instanceof P25Message || message instanceof SyncLossMessage;
|
||||
return message instanceof P25P1Message || message instanceof SyncLossMessage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.hdu;
|
||||
|
||||
@@ -27,20 +24,19 @@ import io.github.dsheirer.edac.Golay18;
|
||||
import io.github.dsheirer.edac.ReedSolomon_63_47_17_P25;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.P25P1DataUnitID;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25P1Message;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HDUMessage extends P25Message
|
||||
public class HDUMessage extends P25P1Message
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(HDUMessage.class);
|
||||
|
||||
private static final int[] GOLAY_WORD_STARTS = {0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198, 216, 234, 252,
|
||||
270, 288, 306, 324, 342, 360, 278, 396, 414, 432, 450, 468, 486, 504, 522, 540, 558, 576, 594, 612, 630};
|
||||
|
||||
private static final int[] CW_HEX_0 = {0, 1, 2, 3, 4, 5, 6};
|
||||
private static final int[] CW_HEX_0 = {0, 1, 2, 3, 4, 5};
|
||||
private static final int[] CW_HEX_1 = {18, 19, 20, 21, 22, 23};
|
||||
private static final int[] CW_HEX_2 = {36, 37, 38, 39, 40, 41};
|
||||
private static final int[] CW_HEX_3 = {54, 55, 56, 57, 58, 59};
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.radio.FullyQualifiedRadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25FullyQualifiedRadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCSourceIDExtension;
|
||||
|
||||
/**
|
||||
* Extended link control word. Base class for adding in the extension word for messages that require two link control
|
||||
* fragments to fit the content.
|
||||
*/
|
||||
public abstract class ExtendedSourceLinkControlWord extends LinkControlWord
|
||||
{
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private LCSourceIDExtension mSourceIDExtension;
|
||||
private FullyQualifiedRadioIdentifier mSourceAddress;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public ExtendedSourceLinkControlWord(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional source ID extension message for a fully qualified radio source.
|
||||
*/
|
||||
protected LCSourceIDExtension getSourceIDExtension()
|
||||
{
|
||||
return mSourceIDExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the extension message.
|
||||
*/
|
||||
public void setSourceIDExtension(LCSourceIDExtension extension)
|
||||
{
|
||||
mSourceIDExtension = extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this message is carrying a source ID extension message.
|
||||
*/
|
||||
protected boolean hasSourceIDExtension()
|
||||
{
|
||||
return mSourceIDExtension != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source address
|
||||
*/
|
||||
public FullyQualifiedRadioIdentifier getSourceAddress()
|
||||
{
|
||||
if(mSourceAddress == null && hasSourceIDExtension())
|
||||
{
|
||||
int radio = getInt(SOURCE_ADDRESS);
|
||||
int wacn = getSourceIDExtension().getWACN();
|
||||
int system = getSourceIDExtension().getSystem();
|
||||
int id = getSourceIDExtension().getId();
|
||||
mSourceAddress = APCO25FullyQualifiedRadioIdentifier.createFrom(radio, wacn, system, id);
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -36,8 +36,8 @@ public enum LinkControlOpcode
|
||||
TELEPHONE_INTERCONNECT_VOICE_CHANNEL_USER("TELEPHONE INTERCONNECT VOICE CHANNEL USER", 6),
|
||||
TELEPHONE_INTERCONNECT_ANSWER_REQUEST("TELEPHONE INTERCONNECT ANSWER REQUEST", 7),
|
||||
RESERVED_08("RESERVED-08", 8),
|
||||
RESERVED_09("RESERVED-09", 9),
|
||||
RESERVED_0A("RESERVED-0A", 10),
|
||||
SOURCE_ID_EXTENSION("SOURCE ID EXTENSION", 9),
|
||||
UNIT_TO_UNIT_VOICE_CHANNEL_USER_EXTENDED("UNIT-TO-UNIT VOICE CHANNEL USER EXTENDED", 10),
|
||||
RESERVED_0B("RESERVED-0B", 11),
|
||||
RESERVED_0C("RESERVED-0C", 12),
|
||||
RESERVED_0D("RESERVED-0D", 13),
|
||||
@@ -52,10 +52,10 @@ public enum LinkControlOpcode
|
||||
CALL_ALERT("CALL ALERT", 22),
|
||||
EXTENDED_FUNCTION_COMMAND("EXTENDED FUNCTION COMMAND", 23),
|
||||
CHANNEL_IDENTIFIER_UPDATE("CHANNEL IDENTIFIER UPDATE", 24),
|
||||
CHANNEL_IDENTIFIER_UPDATE_EXPLICIT("CHANNEL IDENTIFIER UPDATE EXPLICIT", 25),
|
||||
RESERVED_1A("RESERVED-1A", 26),
|
||||
RESERVED_1B("RESERVED-1B", 27),
|
||||
RESERVED_1C("RESERVED-1C", 28),
|
||||
CHANNEL_IDENTIFIER_UPDATE_VU("CHANNEL IDENTIFIER UPDATE EXPLICIT", 25),
|
||||
STATUS_UPDATE_EXTENDED("STATUS UPDATE-SOURCE ID REQUIRED", 26),
|
||||
MESSAGE_UPDATE_EXTENDED("MESSAGE UPDATE-SOURCE ID REQUIRED", 27),
|
||||
EXTENDED_FUNCTION_COMMAND_EXTENDED("EXTENDED FUNCTION COMMAND-SOURCE ID REQUIRED", 28),
|
||||
RESERVED_1D("RESERVED-1D", 29),
|
||||
RESERVED_1E("RESERVED-1E", 30),
|
||||
RESERVED_1F("RESERVED-1F", 31),
|
||||
@@ -69,7 +69,7 @@ public enum LinkControlOpcode
|
||||
ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT("ADJACENT SITE STATUS EXPLICIT", 39),
|
||||
RFSS_STATUS_BROADCAST_EXPLICIT("RFSS STATUS BROADCAST EXPLICIT", 40),
|
||||
NETWORK_STATUS_BROADCAST_EXPLICIT("NETWORK STATUS BROADCAST EXPLICIT", 41),
|
||||
RESERVED_2A("RESERVED-2A", 42),
|
||||
CONVENTIONAL_FALLBACK_INDICATION("CONVENTIONAL FALLBACK INDICATION", 42),
|
||||
RESERVED_2B("RESERVED-2B", 43),
|
||||
RESERVED_2C("RESERVED-2C", 44),
|
||||
RESERVED_2D("RESERVED-2D", 45),
|
||||
@@ -92,15 +92,18 @@ public enum LinkControlOpcode
|
||||
RESERVED_3E("RESERVED-3E", 62),
|
||||
RESERVED_3F("RESERVED-3F", 63),
|
||||
|
||||
MOTOROLA_PATCH_GROUP_VOICE_CHANNEL_USER("PATCH GROUP VOICE CHANNEL USER", 0),
|
||||
MOTOROLA_PATCH_GROUP_VOICE_CHANNEL_UPDATE("PATCH GROUP VOICE CHANNEL UPDATE", 1),
|
||||
MOTOROLA_PATCH_GROUP_ADD("PATCH GROUP ADD", 3),
|
||||
MOTOROLA_PATCH_GROUP_DELETE("PATCH GROUP DELETE", 4),
|
||||
MOTOROLA_UNIT_GPS("UNIT GPS", 6),
|
||||
MOTOROLA_TALK_COMPLETE("TALK_COMPLETE", 15),
|
||||
MOTOROLA_GROUP_REGROUP_VOICE_CHANNEL_USER("MOTOROLA GROUP REGROUP VOICE CHANNEL USER", 0),
|
||||
MOTOROLA_GROUP_REGROUP_VOICE_CHANNEL_UPDATE("MOTOROLA GROUP REGROUP VOICE CHANNEL UPDATE", 1),
|
||||
MOTOROLA_GROUP_REGROUP_ADD("MOTOROLA GROUP REGROUP ADD", 3),
|
||||
MOTOROLA_GROUP_REGROUP_DELETE("MOTOROLA GROUP REGROUP DELETE", 4),
|
||||
MOTOROLA_UNIT_GPS("MOTOROLA UNIT GPS", 6),
|
||||
MOTOROLA_EMERGENCY_ALARM_ACTIVATION("MOTOROLA EMERGENCY ALARM ACTIVATION", 10),
|
||||
MOTOROLA_TALK_COMPLETE("MOTOROLA TALK_COMPLETE", 15),
|
||||
MOTOROLA_RADIO_REPROGRAM_HEADER("MOTOROLA RADIO REPROGRAM HEADER", 21),
|
||||
MOTOROLA_RADIO_REPROGRAM_RECORD("MOTOROLA RADIO REPROGRAM CONTINUATION", 23),
|
||||
MOTOROLA_UNKNOWN("MOTOROLA UNKNOWN", -1),
|
||||
|
||||
L3HARRIS_UNKNOWN_0A("UNKNOWN OPCODE 10", 10),
|
||||
L3HARRIS_RETURN_TO_CONTROL_CHANNEL("UNKNOWN OPCODE 10", 10),
|
||||
L3HARRIS_UNKNOWN_2A("UNKNOWN OPCODE 42", 42),
|
||||
L3HARRIS_UNKNOWN_2B("UNKNOWN OPCODE 43", 43),
|
||||
L3HARRIS_UNKNOWN("L3HARRIS UNKNOWN", -1),
|
||||
@@ -133,19 +136,19 @@ public enum LinkControlOpcode
|
||||
* Motorola Opcodes
|
||||
*/
|
||||
public static final EnumSet<LinkControlOpcode> MOTOROLA_OPCODES =
|
||||
EnumSet.range(MOTOROLA_PATCH_GROUP_VOICE_CHANNEL_USER, MOTOROLA_UNKNOWN);
|
||||
EnumSet.range(MOTOROLA_GROUP_REGROUP_VOICE_CHANNEL_USER, MOTOROLA_UNKNOWN);
|
||||
|
||||
/**
|
||||
* L3Harris Opcodes
|
||||
*/
|
||||
public static final EnumSet<LinkControlOpcode> L3HARRIS_OPCODES = EnumSet.of(L3HARRIS_UNKNOWN_0A,
|
||||
public static final EnumSet<LinkControlOpcode> L3HARRIS_OPCODES = EnumSet.of(L3HARRIS_RETURN_TO_CONTROL_CHANNEL,
|
||||
L3HARRIS_UNKNOWN_2A, L3HARRIS_UNKNOWN_2B, L3HARRIS_UNKNOWN);
|
||||
|
||||
/**
|
||||
* Network/channel related opcodes
|
||||
*/
|
||||
public static final EnumSet<LinkControlOpcode> NETWORK_OPCODES = EnumSet.of(CHANNEL_IDENTIFIER_UPDATE,
|
||||
CHANNEL_IDENTIFIER_UPDATE_EXPLICIT, SYSTEM_SERVICE_BROADCAST, SECONDARY_CONTROL_CHANNEL_BROADCAST,
|
||||
CHANNEL_IDENTIFIER_UPDATE_VU, SYSTEM_SERVICE_BROADCAST, SECONDARY_CONTROL_CHANNEL_BROADCAST,
|
||||
SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT, ADJACENT_SITE_STATUS_BROADCAST,
|
||||
ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT, RFSS_STATUS_BROADCAST, RFSS_STATUS_BROADCAST_EXPLICIT,
|
||||
NETWORK_STATUS_BROADCAST, NETWORK_STATUS_BROADCAST_EXPLICIT, PROTECTION_PARAMETER_BROADCAST);
|
||||
@@ -205,7 +208,7 @@ public enum LinkControlOpcode
|
||||
switch(value)
|
||||
{
|
||||
case 10:
|
||||
return L3HARRIS_UNKNOWN_0A;
|
||||
return L3HARRIS_RETURN_TO_CONTROL_CHANNEL;
|
||||
case 42:
|
||||
return L3HARRIS_UNKNOWN_2A;
|
||||
case 43:
|
||||
@@ -217,17 +220,23 @@ public enum LinkControlOpcode
|
||||
switch(value)
|
||||
{
|
||||
case 0:
|
||||
return MOTOROLA_PATCH_GROUP_VOICE_CHANNEL_USER;
|
||||
return MOTOROLA_GROUP_REGROUP_VOICE_CHANNEL_USER;
|
||||
case 1:
|
||||
return MOTOROLA_PATCH_GROUP_VOICE_CHANNEL_UPDATE;
|
||||
return MOTOROLA_GROUP_REGROUP_VOICE_CHANNEL_UPDATE;
|
||||
case 3:
|
||||
return MOTOROLA_PATCH_GROUP_ADD;
|
||||
return MOTOROLA_GROUP_REGROUP_ADD;
|
||||
case 4:
|
||||
return MOTOROLA_PATCH_GROUP_DELETE;
|
||||
return MOTOROLA_GROUP_REGROUP_DELETE;
|
||||
case 6:
|
||||
return MOTOROLA_UNIT_GPS;
|
||||
case 10:
|
||||
return MOTOROLA_EMERGENCY_ALARM_ACTIVATION;
|
||||
case 15:
|
||||
return MOTOROLA_TALK_COMPLETE;
|
||||
case 21:
|
||||
return MOTOROLA_RADIO_REPROGRAM_HEADER;
|
||||
case 23:
|
||||
return MOTOROLA_RADIO_REPROGRAM_RECORD;
|
||||
default:
|
||||
return MOTOROLA_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -15,66 +14,73 @@
|
||||
*
|
||||
* 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.phase1.message.lc;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.FragmentedIntField;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.message.AbstractMessage;
|
||||
import io.github.dsheirer.module.decode.p25.reference.Vendor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* APCO 25 Link Control Word. This message word is contained in Logical Link Data Unit 1 and Terminator with
|
||||
* Link Control messages.
|
||||
*/
|
||||
public abstract class LinkControlWord
|
||||
public abstract class LinkControlWord extends AbstractMessage
|
||||
{
|
||||
public static final int OCTET_0_BIT_0 = 0;
|
||||
public static final int OCTET_1_BIT_8 = 8;
|
||||
public static final int OCTET_2_BIT_16 = 16;
|
||||
public static final int OCTET_3_BIT_24 = 24;
|
||||
public static final int OCTET_4_BIT_32 = 32;
|
||||
public static final int OCTET_5_BIT_40 = 40;
|
||||
public static final int OCTET_6_BIT_48 = 48;
|
||||
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;
|
||||
|
||||
private static final int ENCRYPTION_FLAG = 0;
|
||||
private static final int STANDARD_VENDOR_ID_FLAG = 1;
|
||||
private static final int[] OPCODE = {2, 3, 4, 5, 6, 7};
|
||||
private static final int[] VENDOR = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
|
||||
private BinaryMessage mMessage;
|
||||
private static final FragmentedIntField OPCODE = FragmentedIntField.of(2, 3, 4, 5, 6, 7);
|
||||
private static final IntField VENDOR = IntField.length8(OCTET_1_BIT_8);
|
||||
private LinkControlOpcode mLinkControlOpcode;
|
||||
private boolean mValid = true;
|
||||
private boolean mValid;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LinkControlWord(BinaryMessage message)
|
||||
public LinkControlWord(CorrectedBinaryMessage message)
|
||||
{
|
||||
mMessage = message;
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binary message sequence for this LCW
|
||||
*/
|
||||
protected BinaryMessage getMessage()
|
||||
{
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the valid flag for this message to mark a flag as invalid (false) or the default value is true.
|
||||
*/
|
||||
public void setValid(boolean valid)
|
||||
{
|
||||
mValid = valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this link control word is valid and has passed all error detection and correction routines.
|
||||
* Indicates if the message passes CRC checks.
|
||||
*/
|
||||
public boolean isValid()
|
||||
{
|
||||
return mValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the valid flag for this message.
|
||||
*/
|
||||
public void setValid(boolean valid)
|
||||
{
|
||||
mValid = valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is an encrypted LCW
|
||||
*/
|
||||
@@ -110,7 +116,7 @@ public abstract class LinkControlWord
|
||||
/**
|
||||
* Lookup the Vendor format for the specified LCW
|
||||
*/
|
||||
public static Vendor getVendor(BinaryMessage binaryMessage)
|
||||
public static Vendor getVendor(CorrectedBinaryMessage binaryMessage)
|
||||
{
|
||||
if(isStandardVendorFormat(binaryMessage))
|
||||
{
|
||||
@@ -140,13 +146,13 @@ public abstract class LinkControlWord
|
||||
*/
|
||||
public int getOpcodeNumber()
|
||||
{
|
||||
return getMessage().getInt(OPCODE);
|
||||
return getInt(OPCODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies the link control word opcode from the binary message.
|
||||
*/
|
||||
public static LinkControlOpcode getOpcode(BinaryMessage binaryMessage)
|
||||
public static LinkControlOpcode getOpcode(CorrectedBinaryMessage binaryMessage)
|
||||
{
|
||||
return LinkControlOpcode.fromValue(binaryMessage.getInt(OPCODE), getVendor(binaryMessage));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -19,14 +19,17 @@
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.l3harris.LCHarrisUnknownOpcode10;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.l3harris.LCHarrisReturnToControlChannel;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.l3harris.LCHarrisUnknownOpcode42;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.l3harris.LCHarrisUnknownOpcode43;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaPatchGroupAdd;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaPatchGroupDelete;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaPatchGroupVoiceChannelUpdate;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaPatchGroupVoiceChannelUser;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaEmergencyAlarmActivation;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaGroupGroupDelete;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaGroupRegroupAdd;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaGroupRegroupVoiceChannelUpdate;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaGroupRegroupVoiceChannelUser;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaRadioReprogramHeader;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaRadioReprogramRecord;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaTalkComplete;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaUnitGPS;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaUnknownOpcode;
|
||||
@@ -34,14 +37,17 @@ import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCAdjacen
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCAdjacentSiteStatusBroadcastExplicit;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCCallAlert;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCCallTermination;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCChannelIdentifierUpdate;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCChannelIdentifierUpdateVU;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCConventionalFallback;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCExtendedFunctionCommand;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCFrequencyBandUpdate;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCFrequencyBandUpdateExplicit;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCExtendedFunctionCommandExtended;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCGroupAffiliationQuery;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCGroupVoiceChannelUpdate;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCGroupVoiceChannelUpdateExplicit;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCGroupVoiceChannelUser;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCMessageUpdate;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCMessageUpdateExtended;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCNetworkStatusBroadcast;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCNetworkStatusBroadcastExplicit;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCProtectionParameterBroadcast;
|
||||
@@ -49,8 +55,10 @@ import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCRFSSSta
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCRFSSStatusBroadcastExplicit;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCSecondaryControlChannelBroadcast;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCSecondaryControlChannelBroadcastExplicit;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCSourceIDExtension;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCStatusQuery;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCStatusUpdate;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCStatusUpdateExtended;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCSystemServiceBroadcast;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCTelephoneInterconnectAnswerRequest;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCTelephoneInterconnectVoiceChannelUser;
|
||||
@@ -58,6 +66,7 @@ import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCUnitAut
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCUnitRegistrationCommand;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCUnitToUnitAnswerRequest;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCUnitToUnitVoiceChannelUser;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCUnitToUnitVoiceChannelUserExtended;
|
||||
|
||||
/**
|
||||
* Factory class for creating link control word (LCW) message parsers.
|
||||
@@ -67,96 +76,114 @@ public class LinkControlWordFactory
|
||||
/**
|
||||
* Creates a link control word from the binary message sequence.
|
||||
*
|
||||
* @param binaryMessage containing the LCW binary message sequence.
|
||||
* @param message containing the LCW binary message sequence.
|
||||
*/
|
||||
public static LinkControlWord create(BinaryMessage binaryMessage)
|
||||
public static LinkControlWord create(CorrectedBinaryMessage message)
|
||||
{
|
||||
LinkControlOpcode opcode = LinkControlWord.getOpcode(binaryMessage);
|
||||
LinkControlOpcode opcode = LinkControlWord.getOpcode(message);
|
||||
switch(opcode)
|
||||
{
|
||||
case ADJACENT_SITE_STATUS_BROADCAST:
|
||||
return new LCAdjacentSiteStatusBroadcast(binaryMessage);
|
||||
return new LCAdjacentSiteStatusBroadcast(message);
|
||||
case ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT:
|
||||
return new LCAdjacentSiteStatusBroadcastExplicit(binaryMessage);
|
||||
return new LCAdjacentSiteStatusBroadcastExplicit(message);
|
||||
case CALL_ALERT:
|
||||
return new LCCallAlert(binaryMessage);
|
||||
return new LCCallAlert(message);
|
||||
case CALL_TERMINATION_OR_CANCELLATION:
|
||||
return new LCCallTermination(binaryMessage);
|
||||
return new LCCallTermination(message);
|
||||
case CHANNEL_IDENTIFIER_UPDATE:
|
||||
return new LCFrequencyBandUpdate(binaryMessage);
|
||||
case CHANNEL_IDENTIFIER_UPDATE_EXPLICIT:
|
||||
return new LCFrequencyBandUpdateExplicit(binaryMessage);
|
||||
return new LCChannelIdentifierUpdate(message);
|
||||
case CHANNEL_IDENTIFIER_UPDATE_VU:
|
||||
return new LCChannelIdentifierUpdateVU(message);
|
||||
case CONVENTIONAL_FALLBACK_INDICATION:
|
||||
return new LCConventionalFallback(message);
|
||||
case EXTENDED_FUNCTION_COMMAND:
|
||||
return new LCExtendedFunctionCommand(binaryMessage);
|
||||
return new LCExtendedFunctionCommand(message);
|
||||
case EXTENDED_FUNCTION_COMMAND_EXTENDED:
|
||||
return new LCExtendedFunctionCommandExtended(message);
|
||||
case GROUP_AFFILIATION_QUERY:
|
||||
return new LCGroupAffiliationQuery(binaryMessage);
|
||||
return new LCGroupAffiliationQuery(message);
|
||||
case GROUP_VOICE_CHANNEL_USER:
|
||||
return new LCGroupVoiceChannelUser(binaryMessage);
|
||||
return new LCGroupVoiceChannelUser(message);
|
||||
case GROUP_VOICE_CHANNEL_UPDATE:
|
||||
return new LCGroupVoiceChannelUpdate(binaryMessage);
|
||||
return new LCGroupVoiceChannelUpdate(message);
|
||||
case GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT:
|
||||
return new LCGroupVoiceChannelUpdateExplicit(binaryMessage);
|
||||
return new LCGroupVoiceChannelUpdateExplicit(message);
|
||||
case MESSAGE_UPDATE:
|
||||
return new LCMessageUpdate(binaryMessage);
|
||||
return new LCMessageUpdate(message);
|
||||
case MESSAGE_UPDATE_EXTENDED:
|
||||
return new LCMessageUpdateExtended(message);
|
||||
case NETWORK_STATUS_BROADCAST:
|
||||
return new LCNetworkStatusBroadcast(binaryMessage);
|
||||
return new LCNetworkStatusBroadcast(message);
|
||||
case NETWORK_STATUS_BROADCAST_EXPLICIT:
|
||||
return new LCNetworkStatusBroadcastExplicit(binaryMessage);
|
||||
return new LCNetworkStatusBroadcastExplicit(message);
|
||||
case PROTECTION_PARAMETER_BROADCAST:
|
||||
return new LCProtectionParameterBroadcast(binaryMessage);
|
||||
return new LCProtectionParameterBroadcast(message);
|
||||
case RFSS_STATUS_BROADCAST:
|
||||
return new LCRFSSStatusBroadcast(binaryMessage);
|
||||
return new LCRFSSStatusBroadcast(message);
|
||||
case RFSS_STATUS_BROADCAST_EXPLICIT:
|
||||
return new LCRFSSStatusBroadcastExplicit(binaryMessage);
|
||||
return new LCRFSSStatusBroadcastExplicit(message);
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST:
|
||||
return new LCSecondaryControlChannelBroadcast(binaryMessage);
|
||||
return new LCSecondaryControlChannelBroadcast(message);
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT:
|
||||
return new LCSecondaryControlChannelBroadcastExplicit(binaryMessage);
|
||||
return new LCSecondaryControlChannelBroadcastExplicit(message);
|
||||
case SOURCE_ID_EXTENSION:
|
||||
return new LCSourceIDExtension(message);
|
||||
case STATUS_QUERY:
|
||||
return new LCStatusQuery(binaryMessage);
|
||||
return new LCStatusQuery(message);
|
||||
case STATUS_UPDATE:
|
||||
return new LCStatusUpdate(binaryMessage);
|
||||
return new LCStatusUpdate(message);
|
||||
case STATUS_UPDATE_EXTENDED:
|
||||
return new LCStatusUpdateExtended(message);
|
||||
case SYSTEM_SERVICE_BROADCAST:
|
||||
return new LCSystemServiceBroadcast(binaryMessage);
|
||||
return new LCSystemServiceBroadcast(message);
|
||||
case TELEPHONE_INTERCONNECT_ANSWER_REQUEST:
|
||||
return new LCTelephoneInterconnectAnswerRequest(binaryMessage);
|
||||
return new LCTelephoneInterconnectAnswerRequest(message);
|
||||
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_USER:
|
||||
return new LCTelephoneInterconnectVoiceChannelUser(binaryMessage);
|
||||
return new LCTelephoneInterconnectVoiceChannelUser(message);
|
||||
case UNIT_AUTHENTICATION_COMMAND:
|
||||
return new LCUnitAuthenticationCommand(binaryMessage);
|
||||
return new LCUnitAuthenticationCommand(message);
|
||||
case UNIT_REGISTRATION_COMMAND:
|
||||
return new LCUnitRegistrationCommand(binaryMessage);
|
||||
return new LCUnitRegistrationCommand(message);
|
||||
case UNIT_TO_UNIT_ANSWER_REQUEST:
|
||||
return new LCUnitToUnitAnswerRequest(binaryMessage);
|
||||
return new LCUnitToUnitAnswerRequest(message);
|
||||
case UNIT_TO_UNIT_VOICE_CHANNEL_USER:
|
||||
return new LCUnitToUnitVoiceChannelUser(binaryMessage);
|
||||
return new LCUnitToUnitVoiceChannelUser(message);
|
||||
case UNIT_TO_UNIT_VOICE_CHANNEL_USER_EXTENDED:
|
||||
return new LCUnitToUnitVoiceChannelUserExtended(message);
|
||||
|
||||
case L3HARRIS_UNKNOWN_0A:
|
||||
return new LCHarrisUnknownOpcode10(binaryMessage);
|
||||
case L3HARRIS_RETURN_TO_CONTROL_CHANNEL:
|
||||
return new LCHarrisReturnToControlChannel(message);
|
||||
case L3HARRIS_UNKNOWN_2A:
|
||||
return new LCHarrisUnknownOpcode42(binaryMessage);
|
||||
return new LCHarrisUnknownOpcode42(message);
|
||||
case L3HARRIS_UNKNOWN_2B:
|
||||
return new LCHarrisUnknownOpcode43(binaryMessage);
|
||||
return new LCHarrisUnknownOpcode43(message);
|
||||
case L3HARRIS_UNKNOWN:
|
||||
return new UnknownLinkControlWord(binaryMessage);
|
||||
return new UnknownLinkControlWord(message);
|
||||
|
||||
case MOTOROLA_PATCH_GROUP_ADD:
|
||||
return new LCMotorolaPatchGroupAdd(binaryMessage);
|
||||
case MOTOROLA_PATCH_GROUP_DELETE:
|
||||
return new LCMotorolaPatchGroupDelete(binaryMessage);
|
||||
case MOTOROLA_PATCH_GROUP_VOICE_CHANNEL_USER:
|
||||
return new LCMotorolaPatchGroupVoiceChannelUser(binaryMessage);
|
||||
case MOTOROLA_GROUP_REGROUP_ADD:
|
||||
return new LCMotorolaGroupRegroupAdd(message);
|
||||
case MOTOROLA_GROUP_REGROUP_DELETE:
|
||||
return new LCMotorolaGroupGroupDelete(message);
|
||||
case MOTOROLA_GROUP_REGROUP_VOICE_CHANNEL_USER:
|
||||
return new LCMotorolaGroupRegroupVoiceChannelUser(message);
|
||||
case MOTOROLA_TALK_COMPLETE:
|
||||
return new LCMotorolaTalkComplete(binaryMessage);
|
||||
case MOTOROLA_PATCH_GROUP_VOICE_CHANNEL_UPDATE:
|
||||
return new LCMotorolaPatchGroupVoiceChannelUpdate(binaryMessage);
|
||||
return new LCMotorolaTalkComplete(message);
|
||||
case MOTOROLA_GROUP_REGROUP_VOICE_CHANNEL_UPDATE:
|
||||
return new LCMotorolaGroupRegroupVoiceChannelUpdate(message);
|
||||
case MOTOROLA_UNIT_GPS:
|
||||
return new LCMotorolaUnitGPS(binaryMessage);
|
||||
return new LCMotorolaUnitGPS(message);
|
||||
case MOTOROLA_RADIO_REPROGRAM_HEADER:
|
||||
return new LCMotorolaRadioReprogramHeader(message);
|
||||
case MOTOROLA_RADIO_REPROGRAM_RECORD:
|
||||
return new LCMotorolaRadioReprogramRecord(message);
|
||||
case MOTOROLA_EMERGENCY_ALARM_ACTIVATION:
|
||||
return new LCMotorolaEmergencyAlarmActivation(message);
|
||||
case MOTOROLA_UNKNOWN:
|
||||
return new LCMotorolaUnknownOpcode(binaryMessage);
|
||||
return new LCMotorolaUnknownOpcode(message);
|
||||
|
||||
default:
|
||||
return new UnknownLinkControlWord(binaryMessage);
|
||||
return new UnknownLinkControlWord(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -15,14 +14,13 @@
|
||||
*
|
||||
* 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.phase1.message.lc;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -36,7 +34,7 @@ public class UnknownLinkControlWord extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public UnknownLinkControlWord(BinaryMessage message)
|
||||
public UnknownLinkControlWord(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.module.decode.p25.IServiceOptionsProvider;
|
||||
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
|
||||
|
||||
/**
|
||||
* Base voice call link control word
|
||||
*/
|
||||
public abstract class VoiceLinkControlMessage extends LinkControlWord implements IServiceOptionsProvider
|
||||
{
|
||||
private static final IntField SERVICE_OPTIONS = IntField.length8(OCTET_2_BIT_16);
|
||||
private VoiceServiceOptions mVoiceServiceOptions;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public VoiceLinkControlMessage(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Service Options for this channel
|
||||
*/
|
||||
public VoiceServiceOptions getServiceOptions()
|
||||
{
|
||||
if(mVoiceServiceOptions == null)
|
||||
{
|
||||
mVoiceServiceOptions = new VoiceServiceOptions(getInt(SERVICE_OPTIONS));
|
||||
}
|
||||
|
||||
return mVoiceServiceOptions;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -19,7 +19,8 @@
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.l3harris;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.radio.RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
@@ -28,20 +29,30 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* L3Harris Unknown Opcode 10 (0x0A)
|
||||
* L3Harris Opcode 10 (0x0A) - This seems to be a 'return to control channel' or 'private data call paging'.
|
||||
* <p>
|
||||
* Observed in a traffic channel carried by a TDU during an SNDCP packet data session. The controller send an 'All
|
||||
* blocks received' PDU to the radio in the middle of a stream of these TDU/LC messages and the traffic channel ended
|
||||
* with Call Termination TDULC messages. So, this may be some form of current data session user information update.
|
||||
* Observed on a phase 1 traffic data channel carried by a TDU during an SNDCP packet data session. The controller sent
|
||||
* an 'All blocks received' PDU to the radio and an 'Activate TDS context' in the middle of a stream of these TDU/LC
|
||||
* messages, and then the radio terminated the traffic channel. So, this may be some form of return to control
|
||||
* channel or maybe a private data call paging where the mobile returns to the control channel to receive the private
|
||||
* data channel grant for another data call
|
||||
*
|
||||
* When the radio returned to the control channel, control sent the following two MAC messages on the Phase 2 control:
|
||||
* LOCCH-U NAC:9/x009 SIGNAL CUSTOM/UNKNOWN VENDOR:HARRIS ID:A4 OPCODE:160 LENGTH:9 MSG:A0A409AC0312014871 (radio 0x014871 go to data channel 0x0312??)
|
||||
* LOCCH-U NAC:9/x009 SIGNAL CUSTOM/UNKNOWN VENDOR:HARRIS ID:A4 OPCODE:172 LENGTH:12 MSG:ACA40C000312014871980418 (from 0x014871 to 0x980418 unit-2-unit data channel grant?)
|
||||
*
|
||||
* Both messages seem to refer to channel 0-786 (0x0312) so this may be a unit-2-unit private Phase 1 call or maybe
|
||||
* a private data call. Radio addresses: 0x014871 and 0x980418
|
||||
*
|
||||
* In a second observation (Rockwall, TX), the control channel used the SNDCP data channel grant to send the
|
||||
* mobile to the data channel and then the data channel transmitted a sequence of TDULCs containing only this message.
|
||||
*
|
||||
*/
|
||||
public class LCHarrisUnknownOpcode10 extends LinkControlWord
|
||||
public class LCHarrisReturnToControlChannel extends LinkControlWord
|
||||
{
|
||||
private static final int[] UNKNOWN_1 = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] TARGET_RADIO = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
42, 43, 44, 45, 46, 47};
|
||||
private static final int[] SOURCE_RADIO = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
|
||||
66, 67, 68, 69, 70, 71};
|
||||
|
||||
private static final IntField UNKNOWN_1 = IntField.length8(OCTET_2_BIT_16);
|
||||
private static final IntField SOURCE_RADIO = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField TARGET_RADIO = IntField.length24(OCTET_6_BIT_48);
|
||||
private RadioIdentifier mSourceRadio;
|
||||
private RadioIdentifier mTargetRadio;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -51,7 +62,7 @@ public class LCHarrisUnknownOpcode10 extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCHarrisUnknownOpcode10(BinaryMessage message)
|
||||
public LCHarrisReturnToControlChannel(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -71,7 +82,7 @@ public class LCHarrisUnknownOpcode10 extends LinkControlWord
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("L3HARRIS UNKNOWN OPCODE 10 ");
|
||||
sb.append("L3HARRIS RETURN TO CONTROL CHANNEL OR PRIVATE DATA CALL PAGING");
|
||||
sb.append(" FM:").append(getSourceRadio());
|
||||
sb.append(" TO:").append(getTargetRadio());
|
||||
sb.append(" UNK:").append(getUnknown());
|
||||
@@ -82,7 +93,7 @@ public class LCHarrisUnknownOpcode10 extends LinkControlWord
|
||||
|
||||
public String getUnknown()
|
||||
{
|
||||
return getMessage().getHex(UNKNOWN_1, 2);
|
||||
return getMessage().getHex(UNKNOWN_1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +103,7 @@ public class LCHarrisUnknownOpcode10 extends LinkControlWord
|
||||
{
|
||||
if(mSourceRadio == null)
|
||||
{
|
||||
mSourceRadio = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_RADIO));
|
||||
mSourceRadio = APCO25RadioIdentifier.createFrom(getInt(SOURCE_RADIO));
|
||||
}
|
||||
|
||||
return mSourceRadio;
|
||||
@@ -105,7 +116,7 @@ public class LCHarrisUnknownOpcode10 extends LinkControlWord
|
||||
{
|
||||
if(mTargetRadio == null)
|
||||
{
|
||||
mTargetRadio = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_RADIO));
|
||||
mTargetRadio = APCO25RadioIdentifier.createTo(getInt(TARGET_RADIO));
|
||||
}
|
||||
|
||||
return mTargetRadio;
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.l3harris;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.Collections;
|
||||
@@ -38,7 +38,7 @@ public class LCHarrisUnknownOpcode42 extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCHarrisUnknownOpcode42(BinaryMessage message)
|
||||
public LCHarrisUnknownOpcode42(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.l3harris;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.Collections;
|
||||
@@ -38,7 +38,7 @@ public class LCHarrisUnknownOpcode43 extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCHarrisUnknownOpcode43(BinaryMessage message)
|
||||
public LCHarrisUnknownOpcode43(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.radio.RadioIdentifier;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Motorola Link Control Opcode 10 appears to be an Emergency Alarm Activation message.
|
||||
*
|
||||
* This was observed in the following sequence:
|
||||
* 1. Radio registers on network.
|
||||
* 2. Radio assigned group and affiliation group
|
||||
* 3. Network acknowledges radio's emergency alarm request
|
||||
* 4. Network sends this message, interspersed with the ack message (3)
|
||||
* 5. Network grants emergency group voice channel to radio and the same talkgroup references in this message, which
|
||||
* is also the assigned talkgroup during initial registration.
|
||||
* 6. Network grants second non-emerg group voice channel to radio and a second (unknown 0x39) talkgroup that may be
|
||||
* a supervisor talkgroup.
|
||||
*
|
||||
* This link control message was also transmitted on active traffic channels.
|
||||
*
|
||||
* Note: the same opcode is used on both on control channel TSBK and traffic channel LCW messaging.
|
||||
*/
|
||||
public class LCMotorolaEmergencyAlarmActivation extends LinkControlWord
|
||||
{
|
||||
private static final IntField GROUP_ADDRESS = IntField.length16(OCTET_2_BIT_16);
|
||||
//There seems to be room for another group address here, octets 4/5??
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private TalkgroupIdentifier mGroupAddress;
|
||||
private RadioIdentifier mSourceAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCMotorolaEmergencyAlarmActivation(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append("**CRC-FAILED** ");
|
||||
}
|
||||
|
||||
if(isEncrypted())
|
||||
{
|
||||
sb.append(" ENCRYPTED");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("MOTOROLA EMERGENCY ALARM ACTIVATION RADIO:").append(getSourceAddress());
|
||||
sb.append(" TALKGROUP:").append(getGroupAddress());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Source Address that activated the emergency alarm.
|
||||
*/
|
||||
public RadioIdentifier getSourceAddress()
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25RadioIdentifier.createTo(getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup to be activated for the emergency voice call
|
||||
*/
|
||||
public TalkgroupIdentifier getGroupAddress()
|
||||
{
|
||||
if(mGroupAddress == null)
|
||||
{
|
||||
mGroupAddress = APCO25Talkgroup.create(getInt(GROUP_ADDRESS));
|
||||
}
|
||||
|
||||
return mGroupAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of identifiers contained in this message
|
||||
*/
|
||||
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getGroupAddress());
|
||||
mIdentifiers.add(getSourceAddress());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Motorola Group Regroup Delete
|
||||
*/
|
||||
public class LCMotorolaGroupGroupDelete extends LinkControlWord
|
||||
{
|
||||
private static final IntField SUPERGROUP = IntField.length16(OCTET_2_BIT_16);
|
||||
private static final IntField PATCHED_GROUP_1 = IntField.length16(OCTET_4_BIT_32);
|
||||
private static final IntField PATCHED_GROUP_2 = IntField.length16(OCTET_6_BIT_48);
|
||||
|
||||
private APCO25PatchGroup mSuperGroup;
|
||||
private TalkgroupIdentifier mPatchedGroup1;
|
||||
private TalkgroupIdentifier mPatchedGroup2;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
public LCMotorolaGroupGroupDelete(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("MOTOROLA GROUP REGROUP DELETE SUPERGROUP:").append(getSuperGroup());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch Group
|
||||
*/
|
||||
public Identifier getSuperGroup()
|
||||
{
|
||||
if(mSuperGroup == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getInt(SUPERGROUP)));
|
||||
patchGroup.addPatchedTalkgroups(getPatchedGroups());
|
||||
mSuperGroup = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
|
||||
return mSuperGroup;
|
||||
}
|
||||
|
||||
public List<TalkgroupIdentifier> getPatchedGroups()
|
||||
{
|
||||
List<TalkgroupIdentifier> patchedGroups = new ArrayList<>();
|
||||
|
||||
if(hasPatchedGroup1())
|
||||
{
|
||||
patchedGroups.add(getPatchedGroup1());
|
||||
}
|
||||
|
||||
if(hasPatchedGroup2())
|
||||
{
|
||||
patchedGroups.add(getPatchedGroup2());
|
||||
}
|
||||
|
||||
return patchedGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patched Group 1
|
||||
*/
|
||||
public TalkgroupIdentifier getPatchedGroup1()
|
||||
{
|
||||
if(mPatchedGroup1 == null)
|
||||
{
|
||||
mPatchedGroup1 = APCO25Talkgroup.create(getInt(PATCHED_GROUP_1));
|
||||
}
|
||||
|
||||
return mPatchedGroup1;
|
||||
}
|
||||
|
||||
public boolean hasPatchedGroup1()
|
||||
{
|
||||
return getInt(PATCHED_GROUP_1) != 0 &&
|
||||
(getInt(SUPERGROUP) != getInt(PATCHED_GROUP_1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Patched Group 2
|
||||
*/
|
||||
public TalkgroupIdentifier getPatchedGroup2()
|
||||
{
|
||||
if(mPatchedGroup2 == null)
|
||||
{
|
||||
mPatchedGroup2 = APCO25Talkgroup.create(getInt(PATCHED_GROUP_2));
|
||||
}
|
||||
|
||||
return mPatchedGroup2;
|
||||
}
|
||||
|
||||
public boolean hasPatchedGroup2()
|
||||
{
|
||||
return getInt(PATCHED_GROUP_2) != 0 &&
|
||||
(getInt(SUPERGROUP) != getInt(PATCHED_GROUP_2));
|
||||
}
|
||||
|
||||
/**
|
||||
* List of identifiers contained in this message
|
||||
*/
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getSuperGroup());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,50 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LCMotorolaPatchGroupAdd extends MotorolaLinkControlWord
|
||||
/**
|
||||
* Motorola Group Regroup Add
|
||||
*/
|
||||
public class LCMotorolaGroupRegroupAdd extends LinkControlWord
|
||||
{
|
||||
private static final int[] PATCH_GROUP = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] PATCHED_GROUP_1 = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] PATCHED_GROUP_2 = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
|
||||
private static final IntField SUPERGROUP = IntField.length16(OCTET_2_BIT_16);
|
||||
private static final IntField PATCHED_GROUP_1 = IntField.length16(OCTET_4_BIT_32);
|
||||
private static final IntField PATCHED_GROUP_2 = IntField.length16(OCTET_6_BIT_48);
|
||||
|
||||
private APCO25PatchGroup mPatchGroup;
|
||||
private TalkgroupIdentifier mPatchedGroup1;
|
||||
private TalkgroupIdentifier mPatchedGroup2;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
public LCMotorolaPatchGroupAdd(BinaryMessage message)
|
||||
public LCMotorolaGroupRegroupAdd(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -52,9 +53,7 @@ public class LCMotorolaPatchGroupAdd extends MotorolaLinkControlWord
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("MOTOROLA ADD PATCH GROUP:").append(getPatchGroup());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
|
||||
sb.append("MOTOROLA GROUP REGROUP ADD SUPERGROUP:").append(getPatchGroup());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -65,7 +64,7 @@ public class LCMotorolaPatchGroupAdd extends MotorolaLinkControlWord
|
||||
{
|
||||
if(mPatchGroup == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getMessage().getInt(PATCH_GROUP)));
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getInt(SUPERGROUP)));
|
||||
patchGroup.addPatchedTalkgroups(getPatchedGroups());
|
||||
mPatchGroup = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
@@ -97,7 +96,7 @@ public class LCMotorolaPatchGroupAdd extends MotorolaLinkControlWord
|
||||
{
|
||||
if(mPatchedGroup1 == null)
|
||||
{
|
||||
mPatchedGroup1 = APCO25Talkgroup.create(getMessage().getInt(PATCHED_GROUP_1));
|
||||
mPatchedGroup1 = APCO25Talkgroup.create(getInt(PATCHED_GROUP_1));
|
||||
}
|
||||
|
||||
return mPatchedGroup1;
|
||||
@@ -105,8 +104,8 @@ public class LCMotorolaPatchGroupAdd extends MotorolaLinkControlWord
|
||||
|
||||
public boolean hasPatchedGroup1()
|
||||
{
|
||||
return getMessage().getInt(PATCHED_GROUP_1) != 0 &&
|
||||
(getMessage().getInt(PATCH_GROUP) != getMessage().getInt(PATCHED_GROUP_1));
|
||||
return getInt(PATCHED_GROUP_1) != 0 &&
|
||||
(getInt(SUPERGROUP) != getInt(PATCHED_GROUP_1));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +115,7 @@ public class LCMotorolaPatchGroupAdd extends MotorolaLinkControlWord
|
||||
{
|
||||
if(mPatchedGroup2 == null)
|
||||
{
|
||||
mPatchedGroup2 = APCO25Talkgroup.create(getMessage().getInt(PATCHED_GROUP_2));
|
||||
mPatchedGroup2 = APCO25Talkgroup.create(getInt(PATCHED_GROUP_2));
|
||||
}
|
||||
|
||||
return mPatchedGroup2;
|
||||
@@ -124,8 +123,7 @@ public class LCMotorolaPatchGroupAdd extends MotorolaLinkControlWord
|
||||
|
||||
public boolean hasPatchedGroup2()
|
||||
{
|
||||
return getMessage().getInt(PATCHED_GROUP_2) != 0 &&
|
||||
(getMessage().getInt(PATCH_GROUP) != getMessage().getInt(PATCHED_GROUP_2));
|
||||
return getInt(PATCHED_GROUP_2) != 0 && (getInt(SUPERGROUP) != getInt(PATCHED_GROUP_2));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.VoiceLinkControlMessage;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Motorola Group Regroup Voice Channel Update
|
||||
*/
|
||||
public class LCMotorolaGroupRegroupVoiceChannelUpdate extends VoiceLinkControlMessage implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final IntField SUPER_GROUP = IntField.length16(OCTET_3_BIT_24);
|
||||
private static final IntField FREQUENCY_BAND = IntField.length4(OCTET_7_BIT_56);
|
||||
private static final IntField CHANNEL_NUMBER = IntField.length12(OCTET_7_BIT_56 + 4);
|
||||
private APCO25PatchGroup mSupergroupAddress;
|
||||
private APCO25Channel mChannel;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCMotorolaGroupRegroupVoiceChannelUpdate(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("MOTOROLA GROUP REGROUP VOICE CHANNEL UPDATE");
|
||||
sb.append(" SUPERGROUP:").append(getSupergroupAddress());
|
||||
sb.append(" CHANNEL:").append(getChannel());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public APCO25PatchGroup getSupergroupAddress()
|
||||
{
|
||||
if(mSupergroupAddress == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getInt(SUPER_GROUP)));
|
||||
mSupergroupAddress = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
|
||||
return mSupergroupAddress;
|
||||
}
|
||||
|
||||
public APCO25Channel getChannel()
|
||||
{
|
||||
if(mChannel == null)
|
||||
{
|
||||
mChannel = APCO25Channel.create(getInt(FREQUENCY_BAND), getInt(CHANNEL_NUMBER));
|
||||
}
|
||||
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = Collections.singletonList(getSupergroupAddress());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IChannelDescriptor> getChannels()
|
||||
{
|
||||
return Collections.singletonList(getChannel());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.VoiceLinkControlMessage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Motorola Group Regroup Voice Channel User.
|
||||
*/
|
||||
public class LCMotorolaGroupRegroupVoiceChannelUser extends VoiceLinkControlMessage
|
||||
{
|
||||
private static final IntField SUPERGROUP_ADDRESS = IntField.length16(OCTET_4_BIT_32);
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
|
||||
private APCO25PatchGroup mSupergroupAddress;
|
||||
private Identifier mSourceAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
public LCMotorolaGroupRegroupVoiceChannelUser(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("MOTOROLA GROUP REGROUP VOICE CHANNEL USER FM:").append(getSourceAddress());
|
||||
sb.append(" TO:").append(getSupergroupAddress());
|
||||
sb.append(" ").append(getServiceOptions());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Supergroup (ie Patch group) address
|
||||
*/
|
||||
public APCO25PatchGroup getSupergroupAddress()
|
||||
{
|
||||
if(mSupergroupAddress == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getInt(SUPERGROUP_ADDRESS)));
|
||||
mSupergroupAddress = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
|
||||
return mSupergroupAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source address
|
||||
*/
|
||||
public Identifier getSourceAddress()
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of identifiers contained in this message
|
||||
*/
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getSupergroupAddress());
|
||||
mIdentifiers.add(getSourceAddress());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LCMotorolaPatchGroupDelete extends MotorolaLinkControlWord
|
||||
{
|
||||
private static final int[] PATCH_GROUP = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] PATCHED_GROUP_1 = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] PATCHED_GROUP_2 = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
|
||||
|
||||
private APCO25PatchGroup mPatchGroup;
|
||||
private TalkgroupIdentifier mPatchedGroup1;
|
||||
private TalkgroupIdentifier mPatchedGroup2;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
public LCMotorolaPatchGroupDelete(BinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("MOTOROLA DELETE PATCH GROUP:").append(getPatchGroup());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch Group
|
||||
*/
|
||||
public Identifier getPatchGroup()
|
||||
{
|
||||
if(mPatchGroup == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getMessage().getInt(PATCH_GROUP)));
|
||||
patchGroup.addPatchedTalkgroups(getPatchedGroups());
|
||||
mPatchGroup = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
|
||||
return mPatchGroup;
|
||||
}
|
||||
|
||||
public List<TalkgroupIdentifier> getPatchedGroups()
|
||||
{
|
||||
List<TalkgroupIdentifier> patchedGroups = new ArrayList<>();
|
||||
|
||||
if(hasPatchedGroup1())
|
||||
{
|
||||
patchedGroups.add(getPatchedGroup1());
|
||||
}
|
||||
|
||||
if(hasPatchedGroup2())
|
||||
{
|
||||
patchedGroups.add(getPatchedGroup2());
|
||||
}
|
||||
|
||||
return patchedGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patched Group 1
|
||||
*/
|
||||
public TalkgroupIdentifier getPatchedGroup1()
|
||||
{
|
||||
if(mPatchedGroup1 == null)
|
||||
{
|
||||
mPatchedGroup1 = APCO25Talkgroup.create(getMessage().getInt(PATCHED_GROUP_1));
|
||||
}
|
||||
|
||||
return mPatchedGroup1;
|
||||
}
|
||||
|
||||
public boolean hasPatchedGroup1()
|
||||
{
|
||||
return getMessage().getInt(PATCHED_GROUP_1) != 0 &&
|
||||
(getMessage().getInt(PATCH_GROUP) != getMessage().getInt(PATCHED_GROUP_1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Patched Group 2
|
||||
*/
|
||||
public TalkgroupIdentifier getPatchedGroup2()
|
||||
{
|
||||
if(mPatchedGroup2 == null)
|
||||
{
|
||||
mPatchedGroup2 = APCO25Talkgroup.create(getMessage().getInt(PATCHED_GROUP_2));
|
||||
}
|
||||
|
||||
return mPatchedGroup2;
|
||||
}
|
||||
|
||||
public boolean hasPatchedGroup2()
|
||||
{
|
||||
return getMessage().getInt(PATCHED_GROUP_2) != 0 &&
|
||||
(getMessage().getInt(PATCH_GROUP) != getMessage().getInt(PATCHED_GROUP_2));
|
||||
}
|
||||
|
||||
/**
|
||||
* List of identifiers contained in this message
|
||||
*/
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getPatchGroup());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Motorola Patch Group Voice Channel Update
|
||||
*/
|
||||
public class LCMotorolaPatchGroupVoiceChannelUpdate extends MotorolaLinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final int[] UNKNOWN_1 = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] PATCH_GROUP = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] UNKNOWN_2 = {40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] UNKNOWN_3 = {48, 49, 50, 51, 52, 53, 54, 55};
|
||||
private static final int[] FREQUENCY_BAND = {56, 57, 58, 59};
|
||||
private static final int[] CHANNEL_NUMBER = {60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private APCO25PatchGroup mPatchGroup;
|
||||
private IChannelDescriptor mChannel;
|
||||
private List<Identifier> mIdentifiers;
|
||||
private List<IChannelDescriptor> mChannels;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCMotorolaPatchGroupVoiceChannelUpdate(BinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("MOTOROLA PATCH VOICE CHANNEL UPDATE");
|
||||
sb.append(" PATCH GROUP:").append(getPatchGroup());
|
||||
sb.append(" CHANNEL:").append(getChannel());
|
||||
sb.append(" UNK1:").append(getUnknownField1());
|
||||
sb.append(" UNK2:").append(getUnknownField2());
|
||||
sb.append(" UNK3:").append(getUnknownField3());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public APCO25PatchGroup getPatchGroup()
|
||||
{
|
||||
if(mPatchGroup == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getMessage().getInt(PATCH_GROUP)));
|
||||
mPatchGroup = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
|
||||
return mPatchGroup;
|
||||
}
|
||||
|
||||
public IChannelDescriptor getChannel()
|
||||
{
|
||||
if(mChannel == null)
|
||||
{
|
||||
mChannel = APCO25Channel.create(getMessage().getInt(FREQUENCY_BAND), getMessage().getInt(CHANNEL_NUMBER));
|
||||
}
|
||||
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
public String getUnknownField1()
|
||||
{
|
||||
return getMessage().getHex(UNKNOWN_1, 2);
|
||||
}
|
||||
public String getUnknownField2()
|
||||
{
|
||||
return getMessage().getHex(UNKNOWN_2, 2);
|
||||
}
|
||||
public String getUnknownField3()
|
||||
{
|
||||
return getMessage().getHex(UNKNOWN_3, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getPatchGroup());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IChannelDescriptor> getChannels()
|
||||
{
|
||||
if(mChannels == null)
|
||||
{
|
||||
mChannels = new ArrayList<>();
|
||||
mChannels.add(getChannel());
|
||||
}
|
||||
|
||||
return mChannels;
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LCMotorolaPatchGroupVoiceChannelUser extends MotorolaLinkControlWord
|
||||
{
|
||||
private static final int[] SERVICE_OPTIONS = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] PATCH_GROUP_ADDRESS = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] SOURCE_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private VoiceServiceOptions mVoiceServiceOptions;
|
||||
private APCO25PatchGroup mGroupAddress;
|
||||
private Identifier mSourceAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
public LCMotorolaPatchGroupVoiceChannelUser(BinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("MOTOROLA PATCH GROUP VOICE CHANNEL USER FM:").append(getSourceAddress());
|
||||
sb.append(" TO:").append(getGroupAddress());
|
||||
sb.append(" ").append(getVoiceServiceOptions());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Service Options for this channel
|
||||
*/
|
||||
public VoiceServiceOptions getVoiceServiceOptions()
|
||||
{
|
||||
if(mVoiceServiceOptions == null)
|
||||
{
|
||||
mVoiceServiceOptions = new VoiceServiceOptions(getMessage().getInt(SERVICE_OPTIONS));
|
||||
}
|
||||
|
||||
return mVoiceServiceOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup address
|
||||
*/
|
||||
public APCO25PatchGroup getGroupAddress()
|
||||
{
|
||||
if(mGroupAddress == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getMessage().getInt(PATCH_GROUP_ADDRESS)));
|
||||
mGroupAddress = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
|
||||
return mGroupAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source address
|
||||
*/
|
||||
public Identifier getSourceAddress()
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of identifiers contained in this message
|
||||
*/
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getGroupAddress());
|
||||
mIdentifiers.add(getSourceAddress());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Motorola Link Control Opcode 0x15.
|
||||
*
|
||||
* Note: I suspect this is some form of radio reprogramming message, possibly used to update encryption.
|
||||
*
|
||||
* I've seen LCOpcode 0x15 and 0x17 twice and in both cases it was sent in a TDULC at the end of a call for the same
|
||||
* radio on the CNYICC system. The header references the talkgroup that the radio is calling, so it may be some form
|
||||
* of dynamic regrouping, but the total content is quite large.
|
||||
*
|
||||
* Note: this seems to only be targeted to certain radios since it wasn't sent at the end of every call.
|
||||
*
|
||||
* Examples observed on traffic channels in TDULC at the end of a call following the Motorola Talk Complete message
|
||||
* for Radio: 15,104,082 (0xE67852) and TG:7101 (0x1BBD)
|
||||
* Example 1
|
||||
*
|
||||
* 1590 1BBD 07 0100 F 8BA / 1BBD=TG, 07=record count, 0100=?, F=sequence number, 8BA=crc checksum
|
||||
* 1790 01 F BEE00 2AE E67 / BEE00=WACN, 2AE=SYS, E67...= RADIO ID
|
||||
* 1790 02 F 852 83ED1081 / ...852=RADIO ID cont.
|
||||
* 1790 03 F E33C03E9B3E
|
||||
* 1790 04 F 35647DE0C00
|
||||
* 1790 05 F C8A83E351E4
|
||||
* 1790 06 F 079F592CF37
|
||||
* 1790 07 F 94B30000000
|
||||
*
|
||||
* Example 2
|
||||
* 1590 1BBD070100 4 955
|
||||
* 1790 01 4 BEE002AEE67
|
||||
* 1790 02 4 85283ED1081
|
||||
* 1790 03 4 E33C03E9B3E
|
||||
* 1790 04 4 35647DE0C00
|
||||
* 1790 05 4 C8A83E351E4
|
||||
* 1790 06 4 079F592CF37
|
||||
* 1790 07 4 94B30000000
|
||||
*
|
||||
* The LCO 15 header starts with the Talkgroup value and seems to identify the count of continuation messages to
|
||||
* follow (0x07). In the LCO 17 continuation messages, the first octet after the vendor seems to be a message record
|
||||
* count ID, ranging from 1 to 7. The next nibble in the continuation messages seems to be a continuation message
|
||||
* sequence number to let you know that the continuation messages are all part of the same sequence.
|
||||
*
|
||||
* The reprogramming payload sequence starts by sending the full SUID for the radio (BEE00.2AE.E67852).
|
||||
*/
|
||||
public class LCMotorolaRadioReprogramHeader extends LinkControlWord
|
||||
{
|
||||
private static final IntField TALKGROUP = IntField.length16(OCTET_2_BIT_16);
|
||||
private static final IntField RECORD_COUNT = IntField.length8(OCTET_4_BIT_32);
|
||||
private static final IntField SEQUENCE_NUMBER = IntField.length4(OCTET_7_BIT_56);
|
||||
private static final IntField SEQUENCE_CHECKSUM = IntField.length12(OCTET_7_BIT_56 + 4);
|
||||
private Identifier mTalkgroup;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCMotorolaRadioReprogramHeader(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append("**CRC-FAILED** ");
|
||||
}
|
||||
|
||||
if(isEncrypted())
|
||||
{
|
||||
sb.append(" ENCRYPTED");
|
||||
}
|
||||
sb.append("MOTOROLA RADIO REPROGRAM HEADER");
|
||||
sb.append(" TG:").append(getTalkgroup());
|
||||
sb.append(" RECORD COUNT:").append(getRecordCount());
|
||||
sb.append(" SEQUENCE:").append(getSequenceNumber());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup
|
||||
*/
|
||||
public Identifier getTalkgroup()
|
||||
{
|
||||
if(mTalkgroup == null)
|
||||
{
|
||||
mTalkgroup = APCO25Talkgroup.create(getInt(TALKGROUP));
|
||||
}
|
||||
|
||||
return mTalkgroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count of continuation messages to follow
|
||||
* @return
|
||||
*/
|
||||
public int getRecordCount()
|
||||
{
|
||||
return getInt(RECORD_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sequence number
|
||||
*/
|
||||
public int getSequenceNumber()
|
||||
{
|
||||
return getInt(SEQUENCE_NUMBER);
|
||||
}
|
||||
|
||||
/**
|
||||
* List of identifiers contained in this message
|
||||
*/
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getTalkgroup());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Motorola Link Control opcode 0x17 (23). This is possibly a radio reprogramming record segment that is used
|
||||
* in combination with LCO 0x15. See notes in header of LCMotorolaRadioReprogramHeader class.
|
||||
*/
|
||||
public class LCMotorolaRadioReprogramRecord extends LinkControlWord
|
||||
{
|
||||
private static final IntField RECORD_NUMBER = IntField.length8(OCTET_2_BIT_16);
|
||||
private static final IntField SEQUENCE_NUMBER = IntField.length4(OCTET_3_BIT_24);
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCMotorolaRadioReprogramRecord(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append("**CRC-FAILED** ");
|
||||
}
|
||||
|
||||
if(isEncrypted())
|
||||
{
|
||||
sb.append(" ENCRYPTED");
|
||||
}
|
||||
|
||||
sb.append("MOTOROLA RADIO REPROGRAM RECORD:").append(getRecordNumber());
|
||||
sb.append(" OF SEQUENCE:").append(getSequenceNumber());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Record number
|
||||
*/
|
||||
public int getRecordNumber()
|
||||
{
|
||||
return getInt(RECORD_NUMBER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sequence number
|
||||
*/
|
||||
public int getSequenceNumber()
|
||||
{
|
||||
return getInt(SEQUENCE_NUMBER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,29 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -35,10 +32,9 @@ import java.util.List;
|
||||
*/
|
||||
public class LCMotorolaTalkComplete extends LinkControlWord
|
||||
{
|
||||
private static final int[] UNKNOWN_FIELD_1 = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] UNKNOWN_FIELD_2 = {40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
|
||||
67, 68, 69, 70, 71};
|
||||
private static final IntField UNKNOWN_FIELD_1 = IntField.length8(OCTET_2_BIT_16);
|
||||
private static final IntField UNKNOWN_FIELD_2 = IntField.length8(OCTET_2_BIT_16);
|
||||
private static final IntField ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
|
||||
private Identifier mAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -48,7 +44,7 @@ public class LCMotorolaTalkComplete extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCMotorolaTalkComplete(BinaryMessage message)
|
||||
public LCMotorolaTalkComplete(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -72,19 +68,18 @@ public class LCMotorolaTalkComplete extends LinkControlWord
|
||||
sb.append(" BY:").append(getAddress());
|
||||
sb.append(" UNK1:").append(getUnknownField1());
|
||||
sb.append(" UNK2:").append(getUnknownField2());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getUnknownField1()
|
||||
{
|
||||
return getMessage().getHex(UNKNOWN_FIELD_1, 2);
|
||||
return getMessage().getHex(UNKNOWN_FIELD_1);
|
||||
}
|
||||
|
||||
public String getUnknownField2()
|
||||
{
|
||||
return getMessage().getHex(UNKNOWN_FIELD_2, 2);
|
||||
return getMessage().getHex(UNKNOWN_FIELD_2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +89,7 @@ public class LCMotorolaTalkComplete extends LinkControlWord
|
||||
{
|
||||
if(mAddress == null)
|
||||
{
|
||||
mAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(ADDRESS));
|
||||
mAddress = APCO25RadioIdentifier.createFrom(getInt(ADDRESS));
|
||||
}
|
||||
|
||||
return mAddress;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
* 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
|
||||
@@ -19,30 +19,39 @@
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.FragmentedIntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import java.util.Collections;
|
||||
import io.github.dsheirer.module.decode.dmr.identifier.P25Location;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
||||
|
||||
/**
|
||||
* Motorola Unit Self-Reported GPS Location
|
||||
*/
|
||||
public class LCMotorolaUnitGPS extends MotorolaLinkControlWord
|
||||
public class LCMotorolaUnitGPS extends LinkControlWord
|
||||
{
|
||||
private static final double LATITUDE_MULTIPLIER = 90.0 / 0x7FFFFF;
|
||||
private static final double LONGITUDE_MULTIPLIER = 180.0 / 0x7FFFFF;
|
||||
|
||||
private static final int[] UNKNOWN = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int LATITUDE_SIGN = 24;
|
||||
private static final int[] LATITUDE = {25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final FragmentedIntField LATITUDE = FragmentedIntField.of(25, 26, 27, 28, 29, 30, 31, 32, 33,
|
||||
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47);
|
||||
private static final int LONGITUDE_SIGN = 48;
|
||||
private static final int[] LONGITUDE = {49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71};
|
||||
private static final FragmentedIntField LONGITUDE = FragmentedIntField.of(49, 50, 51, 52, 53, 54, 55, 56,
|
||||
57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71);
|
||||
|
||||
private P25Location mLocation;
|
||||
private GeoPosition mGeoPosition;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param message binary
|
||||
*/
|
||||
public LCMotorolaUnitGPS(BinaryMessage message)
|
||||
public LCMotorolaUnitGPS(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -55,13 +64,41 @@ public class LCMotorolaUnitGPS extends MotorolaLinkControlWord
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* GPS Location
|
||||
* @return location in decimal degrees
|
||||
*/
|
||||
public P25Location getLocation()
|
||||
{
|
||||
if(mLocation == null)
|
||||
{
|
||||
mLocation = P25Location.createFrom(getLatitude(), getLongitude());
|
||||
}
|
||||
|
||||
return mLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Geo position
|
||||
* @return position
|
||||
*/
|
||||
public GeoPosition getGeoPosition()
|
||||
{
|
||||
if(mGeoPosition == null)
|
||||
{
|
||||
mGeoPosition = new GeoPosition(getLatitude(), getLongitude());
|
||||
}
|
||||
|
||||
return mGeoPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* GPS Latitude value.
|
||||
* @return value in decimal degrees
|
||||
*/
|
||||
public double getLatitude()
|
||||
{
|
||||
return getMessage().getInt(LATITUDE) * LATITUDE_MULTIPLIER * (getMessage().get(LATITUDE_SIGN) ? -1 : 1);
|
||||
return getInt(LATITUDE) * LATITUDE_MULTIPLIER * (getMessage().get(LATITUDE_SIGN) ? -1 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,7 +107,7 @@ public class LCMotorolaUnitGPS extends MotorolaLinkControlWord
|
||||
*/
|
||||
public double getLongitude()
|
||||
{
|
||||
return getMessage().getInt(LONGITUDE) * LONGITUDE_MULTIPLIER * (getMessage().get(LONGITUDE_SIGN) ? -1 : 1);
|
||||
return getInt(LONGITUDE) * LONGITUDE_MULTIPLIER * (getMessage().get(LONGITUDE_SIGN) ? -1 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,6 +116,12 @@ public class LCMotorolaUnitGPS extends MotorolaLinkControlWord
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
return Collections.emptyList();
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getLocation());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -15,28 +14,28 @@
|
||||
*
|
||||
* 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.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Unknown link control word.
|
||||
*/
|
||||
public class LCMotorolaUnknownOpcode extends MotorolaLinkControlWord
|
||||
public class LCMotorolaUnknownOpcode extends LinkControlWord
|
||||
{
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCMotorolaUnknownOpcode(BinaryMessage message)
|
||||
public LCMotorolaUnknownOpcode(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -51,7 +50,7 @@ public class LCMotorolaUnknownOpcode extends MotorolaLinkControlWord
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(" MOTOROLA UNKNOWN/UNRECOGNIZED OPCODE:").append(getOpcode());
|
||||
sb.append(" MOTOROLA UNKNOWN OPCODE:").append(getOpcodeNumber());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25Lra;
|
||||
@@ -33,7 +31,6 @@ import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.SystemServiceClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -42,13 +39,13 @@ import java.util.List;
|
||||
*/
|
||||
public class LCAdjacentSiteStatusBroadcast extends LinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final int[] LRA = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] SYSTEM = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] RFSS = {32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] SITE = {40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] FREQUENCY_BAND = {48, 49, 50, 51};
|
||||
private static final int[] CHANNEL_NUMBER = {52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
|
||||
private static final int[] SERVICE_CLASS = {64, 65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField LRA = IntField.length8(OCTET_1_BIT_8);
|
||||
private static final IntField SYSTEM = IntField.length12(OCTET_2_BIT_16 + 4);
|
||||
private static final IntField RFSS = IntField.length8(OCTET_4_BIT_32);
|
||||
private static final IntField SITE = IntField.length8(OCTET_5_BIT_40);
|
||||
private static final IntField FREQUENCY_BAND = IntField.length4(OCTET_6_BIT_48);
|
||||
private static final IntField CHANNEL_NUMBER = IntField.length12(OCTET_6_BIT_48 + 4);
|
||||
private static final IntField SERVICE_CLASS = IntField.length8(OCTET_8_BIT_64);
|
||||
|
||||
private List<Identifier> mIdentifiers;
|
||||
private Identifier mLRA;
|
||||
@@ -63,7 +60,7 @@ public class LCAdjacentSiteStatusBroadcast extends LinkControlWord implements IF
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCAdjacentSiteStatusBroadcast(BinaryMessage message)
|
||||
public LCAdjacentSiteStatusBroadcast(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -85,7 +82,7 @@ public class LCAdjacentSiteStatusBroadcast extends LinkControlWord implements IF
|
||||
{
|
||||
if(mLRA == null)
|
||||
{
|
||||
mLRA = APCO25Lra.create(getMessage().getInt(LRA));
|
||||
mLRA = APCO25Lra.create(getInt(LRA));
|
||||
}
|
||||
|
||||
return mLRA;
|
||||
@@ -95,7 +92,7 @@ public class LCAdjacentSiteStatusBroadcast extends LinkControlWord implements IF
|
||||
{
|
||||
if(mSystem == null)
|
||||
{
|
||||
mSystem = APCO25System.create(getMessage().getInt(SYSTEM));
|
||||
mSystem = APCO25System.create(getInt(SYSTEM));
|
||||
}
|
||||
|
||||
return mSystem;
|
||||
@@ -105,7 +102,7 @@ public class LCAdjacentSiteStatusBroadcast extends LinkControlWord implements IF
|
||||
{
|
||||
if(mRFSS == null)
|
||||
{
|
||||
mRFSS = APCO25Rfss.create(getMessage().getInt(RFSS));
|
||||
mRFSS = APCO25Rfss.create(getInt(RFSS));
|
||||
}
|
||||
|
||||
return mRFSS;
|
||||
@@ -115,7 +112,7 @@ public class LCAdjacentSiteStatusBroadcast extends LinkControlWord implements IF
|
||||
{
|
||||
if(mSite == null)
|
||||
{
|
||||
mSite = APCO25Site.create(getMessage().getInt(SITE));
|
||||
mSite = APCO25Site.create(getInt(SITE));
|
||||
}
|
||||
|
||||
return mSite;
|
||||
@@ -125,8 +122,7 @@ public class LCAdjacentSiteStatusBroadcast extends LinkControlWord implements IF
|
||||
{
|
||||
if(mChannel == null)
|
||||
{
|
||||
mChannel = APCO25Channel.create(getMessage().getInt(FREQUENCY_BAND),
|
||||
getMessage().getInt(CHANNEL_NUMBER));
|
||||
mChannel = APCO25Channel.create(getInt(FREQUENCY_BAND), getInt(CHANNEL_NUMBER));
|
||||
}
|
||||
|
||||
return mChannel;
|
||||
@@ -136,7 +132,7 @@ public class LCAdjacentSiteStatusBroadcast extends LinkControlWord implements IF
|
||||
{
|
||||
if(mSystemServiceClass == null)
|
||||
{
|
||||
mSystemServiceClass = new SystemServiceClass(getMessage().getInt(SERVICE_CLASS));
|
||||
mSystemServiceClass = new SystemServiceClass(getInt(SERVICE_CLASS));
|
||||
}
|
||||
|
||||
return mSystemServiceClass;
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25Lra;
|
||||
@@ -32,23 +30,23 @@ import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25ExplicitCha
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.SystemServiceClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Secondary control channel broadcast explicit information for V/UHF channels
|
||||
* Adjacent site status broadcast (ie neighbor).
|
||||
*/
|
||||
public class LCAdjacentSiteStatusBroadcastExplicit extends LinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final int[] LRA = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] DOWNLINK_FREQUENCY_BAND = {16, 17, 18, 19};
|
||||
private static final int[] DOWNLINK_CHANNEL_NUMBER = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] RFSS = {32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] SITE = {40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] UPLINK_FREQUENCY_BAND = {48, 49, 50, 51};
|
||||
private static final int[] UPLINK_CHANNEL_NUMBER = {52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
|
||||
private static final int[] SERVICE_CLASS = {64, 65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField LRA = IntField.length8(OCTET_1_BIT_8);
|
||||
private static final IntField DOWNLINK_FREQUENCY_BAND = IntField.length4(OCTET_2_BIT_16);
|
||||
private static final IntField DOWNLINK_CHANNEL_NUMBER = IntField.length12(OCTET_2_BIT_16 + 4);
|
||||
private static final IntField RFSS = IntField.length8(OCTET_4_BIT_32);
|
||||
private static final IntField SITE = IntField.length8(OCTET_5_BIT_40);
|
||||
private static final IntField UPLINK_FREQUENCY_BAND = IntField.length4(OCTET_6_BIT_48);
|
||||
private static final IntField UPLINK_CHANNEL_NUMBER = IntField.length12(OCTET_6_BIT_48 + 4);
|
||||
private static final IntField SERVICE_CLASS = IntField.length8(OCTET_8_BIT_64);
|
||||
|
||||
private List<Identifier> mIdentifiers;
|
||||
private Identifier mLRA;
|
||||
@@ -62,7 +60,7 @@ public class LCAdjacentSiteStatusBroadcastExplicit extends LinkControlWord imple
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCAdjacentSiteStatusBroadcastExplicit(BinaryMessage message)
|
||||
public LCAdjacentSiteStatusBroadcastExplicit(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -83,7 +81,7 @@ public class LCAdjacentSiteStatusBroadcastExplicit extends LinkControlWord imple
|
||||
{
|
||||
if(mLRA == null)
|
||||
{
|
||||
mLRA = APCO25Lra.create(getMessage().getInt(LRA));
|
||||
mLRA = APCO25Lra.create(getInt(LRA));
|
||||
}
|
||||
|
||||
return mLRA;
|
||||
@@ -93,7 +91,7 @@ public class LCAdjacentSiteStatusBroadcastExplicit extends LinkControlWord imple
|
||||
{
|
||||
if(mRFSS == null)
|
||||
{
|
||||
mRFSS = APCO25Rfss.create(getMessage().getInt(RFSS));
|
||||
mRFSS = APCO25Rfss.create(getInt(RFSS));
|
||||
}
|
||||
|
||||
return mRFSS;
|
||||
@@ -103,7 +101,7 @@ public class LCAdjacentSiteStatusBroadcastExplicit extends LinkControlWord imple
|
||||
{
|
||||
if(mSite == null)
|
||||
{
|
||||
mSite = APCO25Site.create(getMessage().getInt(SITE));
|
||||
mSite = APCO25Site.create(getInt(SITE));
|
||||
}
|
||||
|
||||
return mSite;
|
||||
@@ -113,9 +111,8 @@ public class LCAdjacentSiteStatusBroadcastExplicit extends LinkControlWord imple
|
||||
{
|
||||
if(mChannel == null)
|
||||
{
|
||||
mChannel = APCO25ExplicitChannel.create(getMessage().getInt(DOWNLINK_FREQUENCY_BAND),
|
||||
getMessage().getInt(DOWNLINK_CHANNEL_NUMBER), getMessage().getInt(UPLINK_FREQUENCY_BAND),
|
||||
getMessage().getInt(UPLINK_CHANNEL_NUMBER));
|
||||
mChannel = APCO25ExplicitChannel.create(getInt(DOWNLINK_FREQUENCY_BAND), getInt(DOWNLINK_CHANNEL_NUMBER),
|
||||
getInt(UPLINK_FREQUENCY_BAND), getInt(UPLINK_CHANNEL_NUMBER));
|
||||
}
|
||||
|
||||
return mChannel;
|
||||
@@ -125,7 +122,7 @@ public class LCAdjacentSiteStatusBroadcastExplicit extends LinkControlWord imple
|
||||
{
|
||||
if(mSystemServiceClass == null)
|
||||
{
|
||||
mSystemServiceClass = new SystemServiceClass(getMessage().getInt(SERVICE_CLASS));
|
||||
mSystemServiceClass = new SystemServiceClass(getInt(SERVICE_CLASS));
|
||||
}
|
||||
|
||||
return mSystemServiceClass;
|
||||
@@ -152,8 +149,6 @@ public class LCAdjacentSiteStatusBroadcastExplicit extends LinkControlWord imple
|
||||
@Override
|
||||
public List<IChannelDescriptor> getChannels()
|
||||
{
|
||||
List<IChannelDescriptor> channels = new ArrayList<>();
|
||||
channels.add(getChannel());
|
||||
return channels;
|
||||
return Collections.singletonList(getChannel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -35,12 +32,8 @@ import java.util.List;
|
||||
*/
|
||||
public class LCCallAlert extends LinkControlWord
|
||||
{
|
||||
private static final int[] RESERVED = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] TARGET_ADDRESS = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
42, 43, 44, 45, 46, 47};
|
||||
private static final int[] SOURCE_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private Identifier mTargetAddress;
|
||||
private Identifier mSourceAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -50,7 +43,7 @@ public class LCCallAlert extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCCallAlert(BinaryMessage message)
|
||||
public LCCallAlert(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -71,7 +64,7 @@ public class LCCallAlert extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
@@ -84,7 +77,7 @@ public class LCCallAlert extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -37,10 +34,7 @@ public class LCCallTermination extends LinkControlWord
|
||||
{
|
||||
private static final int MOTOROLA_SYSTEM_CONTROLLER = 0xFFFFFD;
|
||||
private static final int HARRIS_SYSTEM_CONTROLLER = 0;
|
||||
|
||||
private static final int[] ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
|
||||
67, 68, 69, 70, 71};
|
||||
|
||||
private static final IntField ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private Identifier mAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
@@ -49,7 +43,7 @@ public class LCCallTermination extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCCallTermination(BinaryMessage message)
|
||||
public LCCallTermination(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -69,7 +63,7 @@ public class LCCallTermination extends LinkControlWord
|
||||
{
|
||||
if(mAddress == null)
|
||||
{
|
||||
mAddress = APCO25Talkgroup.create(getMessage().getInt(ADDRESS));
|
||||
mAddress = APCO25Talkgroup.create(getInt(ADDRESS));
|
||||
}
|
||||
|
||||
return mAddress;
|
||||
@@ -80,7 +74,7 @@ public class LCCallTermination extends LinkControlWord
|
||||
*/
|
||||
public boolean isNetworkCommandedTeardown()
|
||||
{
|
||||
int address = getMessage().getInt(ADDRESS);
|
||||
int address = getInt(ADDRESS);
|
||||
return address == MOTOROLA_SYSTEM_CONTROLLER || address == HARRIS_SYSTEM_CONTROLLER;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,54 +1,52 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.FragmentedIntField;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.bits.LongField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBand;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Echo of the status update from a subscriber when the destination of the update is another subscriber unit.
|
||||
* Channel identifier update
|
||||
*/
|
||||
public class LCFrequencyBandUpdate extends LinkControlWord implements IFrequencyBand
|
||||
public class LCChannelIdentifierUpdate extends LinkControlWord implements IFrequencyBand
|
||||
{
|
||||
private static final int[] FREQUENCY_BAND_IDENTIFIER = {8, 9, 10, 11};
|
||||
private static final int[] BANDWIDTH = {12, 13, 14, 15, 16, 17, 18, 19, 20};
|
||||
private static final IntField FREQUENCY_BAND_IDENTIFIER = IntField.length4(OCTET_1_BIT_8);
|
||||
private static final FragmentedIntField BANDWIDTH = FragmentedIntField.of(12, 13, 14, 15, 16, 17, 18, 19, 20);
|
||||
private static final int TRANSMIT_OFFSET_SIGN = 21;
|
||||
private static final int[] TRANSMIT_OFFSET = {22, 23, 24, 25, 26, 27, 28, 29};
|
||||
private static final int[] CHANNEL_SPACING = {30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] BASE_FREQUENCY = {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};
|
||||
private static final FragmentedIntField TRANSMIT_OFFSET = FragmentedIntField.of(22, 23, 24, 25, 26, 27, 28, 29);
|
||||
private static final FragmentedIntField CHANNEL_SPACING = FragmentedIntField.of(30, 31, 32, 33, 34, 35, 36, 37, 38, 39);
|
||||
private static final LongField BASE_FREQUENCY = LongField.length32(OCTET_5_BIT_40);
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCFrequencyBandUpdate(BinaryMessage message)
|
||||
public LCChannelIdentifierUpdate(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -68,31 +66,31 @@ public class LCFrequencyBandUpdate extends LinkControlWord implements IFrequency
|
||||
@Override
|
||||
public int getIdentifier()
|
||||
{
|
||||
return getMessage().getInt(FREQUENCY_BAND_IDENTIFIER);
|
||||
return getInt(FREQUENCY_BAND_IDENTIFIER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChannelSpacing()
|
||||
{
|
||||
return getMessage().getInt(CHANNEL_SPACING) * 125l;
|
||||
return getInt(CHANNEL_SPACING) * 125l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBaseFrequency()
|
||||
{
|
||||
return getMessage().getLong(BASE_FREQUENCY) * 5l;
|
||||
return getLong(BASE_FREQUENCY) * 5l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBandwidth()
|
||||
{
|
||||
return getMessage().getInt(BANDWIDTH) * 125;
|
||||
return getInt(BANDWIDTH) * 125;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTransmitOffset()
|
||||
{
|
||||
long offset = getMessage().getLong(TRANSMIT_OFFSET) * getChannelSpacing();
|
||||
long offset = getInt(TRANSMIT_OFFSET) * getChannelSpacing();
|
||||
|
||||
if(!getMessage().get(TRANSMIT_OFFSET_SIGN))
|
||||
{
|
||||
@@ -107,7 +105,7 @@ public class LCFrequencyBandUpdate extends LinkControlWord implements IFrequency
|
||||
*/
|
||||
public boolean hasTransmitOffset()
|
||||
{
|
||||
return getMessage().getInt(TRANSMIT_OFFSET) != 0x80;
|
||||
return getInt(TRANSMIT_OFFSET) != 0x80;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,54 +1,52 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.FragmentedIntField;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.bits.LongField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBand;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Identifier update explicit
|
||||
* Channel identifier update VHF/UHF
|
||||
*/
|
||||
public class LCFrequencyBandUpdateExplicit extends LinkControlWord implements IFrequencyBand
|
||||
public class LCChannelIdentifierUpdateVU extends LinkControlWord implements IFrequencyBand
|
||||
{
|
||||
private static final int[] FREQUENCY_BAND_IDENTIFIER = {8, 9, 10, 11};
|
||||
private static final int[] BANDWIDTH = {12, 13, 14, 15};
|
||||
private static final IntField FREQUENCY_BAND_IDENTIFIER = IntField.length4(OCTET_1_BIT_8);
|
||||
private static final IntField BANDWIDTH = IntField.length4(OCTET_1_BIT_8 + 4);
|
||||
private static final int TRANSMIT_OFFSET_SIGN = 16;
|
||||
private static final int[] TRANSMIT_OFFSET = {17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29};
|
||||
private static final int[] CHANNEL_SPACING = {30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] BASE_FREQUENCY = {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};
|
||||
private static final FragmentedIntField TRANSMIT_OFFSET = FragmentedIntField.of(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29);
|
||||
private static final FragmentedIntField CHANNEL_SPACING = FragmentedIntField.of(30, 31, 32, 33, 34, 35, 36, 37, 38, 39);
|
||||
private static final LongField BASE_FREQUENCY = LongField.length32(OCTET_5_BIT_40);
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCFrequencyBandUpdateExplicit(BinaryMessage message)
|
||||
public LCChannelIdentifierUpdateVU(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -68,25 +66,25 @@ public class LCFrequencyBandUpdateExplicit extends LinkControlWord implements IF
|
||||
@Override
|
||||
public int getIdentifier()
|
||||
{
|
||||
return getMessage().getInt(FREQUENCY_BAND_IDENTIFIER);
|
||||
return getInt(FREQUENCY_BAND_IDENTIFIER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChannelSpacing()
|
||||
{
|
||||
return getMessage().getInt(CHANNEL_SPACING) * 125l;
|
||||
return getInt(CHANNEL_SPACING) * 125l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBaseFrequency()
|
||||
{
|
||||
return getMessage().getLong(BASE_FREQUENCY) * 5l;
|
||||
return getLong(BASE_FREQUENCY) * 5l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBandwidth()
|
||||
{
|
||||
int bandwidth = getMessage().getInt(BANDWIDTH);
|
||||
int bandwidth = getInt(BANDWIDTH);
|
||||
|
||||
if(bandwidth == 0x4)
|
||||
{
|
||||
@@ -103,7 +101,7 @@ public class LCFrequencyBandUpdateExplicit extends LinkControlWord implements IF
|
||||
@Override
|
||||
public long getTransmitOffset()
|
||||
{
|
||||
long offset = getMessage().getLong(TRANSMIT_OFFSET) * getChannelSpacing();
|
||||
long offset = getInt(TRANSMIT_OFFSET) * getChannelSpacing();
|
||||
|
||||
if(!getMessage().get(TRANSMIT_OFFSET_SIGN))
|
||||
{
|
||||
@@ -118,7 +116,7 @@ public class LCFrequencyBandUpdateExplicit extends LinkControlWord implements IF
|
||||
*/
|
||||
public boolean hasTransmitOffset()
|
||||
{
|
||||
return getMessage().getInt(TRANSMIT_OFFSET) != 0x80;
|
||||
return getInt(TRANSMIT_OFFSET) != 0x80;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Conventional fallback sent on the outbound channel to indicate that the repeater sending it is providing conventional
|
||||
* fallback service and to indicate which users should use it.
|
||||
*/
|
||||
public class LCConventionalFallback extends LinkControlWord
|
||||
{
|
||||
private static final IntField FALLBACK_CHANNEL_ID_1 = IntField.length8(OCTET_3_BIT_24);
|
||||
private static final IntField FALLBACK_CHANNEL_ID_2 = IntField.length8(OCTET_4_BIT_32);
|
||||
private static final IntField FALLBACK_CHANNEL_ID_3 = IntField.length8(OCTET_5_BIT_40);
|
||||
private static final IntField FALLBACK_CHANNEL_ID_4 = IntField.length8(OCTET_6_BIT_48);
|
||||
private static final IntField FALLBACK_CHANNEL_ID_5 = IntField.length8(OCTET_7_BIT_56);
|
||||
private static final IntField FALLBACK_CHANNEL_ID_6 = IntField.length8(OCTET_8_BIT_64);
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCConventionalFallback(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append(" [CRC ERROR]");
|
||||
}
|
||||
sb.append(" CONVENTIONAL FALLBACK CHANNELS 1:").append(getFallbackChannel1());
|
||||
sb.append(" 2:").append(getFallbackChannel2());
|
||||
sb.append(" 3:").append(getFallbackChannel3());
|
||||
sb.append(" 4:").append(getFallbackChannel4());
|
||||
sb.append(" 5:").append(getFallbackChannel5());
|
||||
sb.append(" 6:").append(getFallbackChannel6());
|
||||
|
||||
return super.toString();
|
||||
}
|
||||
|
||||
public int getFallbackChannel1()
|
||||
{
|
||||
return getInt(FALLBACK_CHANNEL_ID_1);
|
||||
}
|
||||
|
||||
public int getFallbackChannel2()
|
||||
{
|
||||
return getInt(FALLBACK_CHANNEL_ID_2);
|
||||
}
|
||||
|
||||
public int getFallbackChannel3()
|
||||
{
|
||||
return getInt(FALLBACK_CHANNEL_ID_3);
|
||||
}
|
||||
|
||||
public int getFallbackChannel4()
|
||||
{
|
||||
return getInt(FALLBACK_CHANNEL_ID_4);
|
||||
}
|
||||
|
||||
public int getFallbackChannel5()
|
||||
{
|
||||
return getInt(FALLBACK_CHANNEL_ID_5);
|
||||
}
|
||||
|
||||
public int getFallbackChannel6()
|
||||
{
|
||||
return getInt(FALLBACK_CHANNEL_ID_6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* 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
|
||||
@@ -19,12 +19,12 @@
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.ExtendedFunction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -33,11 +33,9 @@ import java.util.List;
|
||||
*/
|
||||
public class LCExtendedFunctionCommand extends LinkControlWord
|
||||
{
|
||||
private static final int[] EXTENDED_FUNCTION = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] EXTENDED_FUNCTION_ARGUMENTS = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
|
||||
38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] TARGET_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField EXTENDED_FUNCTION = IntField.length16(OCTET_1_BIT_8);
|
||||
private static final IntField EXTENDED_FUNCTION_ARGUMENTS = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
|
||||
private Identifier mTargetAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -47,7 +45,7 @@ public class LCExtendedFunctionCommand extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCExtendedFunctionCommand(BinaryMessage message)
|
||||
public LCExtendedFunctionCommand(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -67,7 +65,7 @@ public class LCExtendedFunctionCommand extends LinkControlWord
|
||||
*/
|
||||
public ExtendedFunction getExtendedFunction()
|
||||
{
|
||||
return ExtendedFunction.fromValue(getMessage().getInt(EXTENDED_FUNCTION));
|
||||
return ExtendedFunction.fromValue(getInt(EXTENDED_FUNCTION));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +73,7 @@ public class LCExtendedFunctionCommand extends LinkControlWord
|
||||
*/
|
||||
public String getExtendedFunctionArguments()
|
||||
{
|
||||
return getMessage().getHex(EXTENDED_FUNCTION_ARGUMENTS, 6);
|
||||
return getMessage().getHex(EXTENDED_FUNCTION_ARGUMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +83,7 @@ public class LCExtendedFunctionCommand extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.radio.FullyQualifiedRadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25FullyQualifiedRadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.ExtendedSourceLinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.ExtendedFunction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Extended function command to a target address with an extended SUID
|
||||
*/
|
||||
public class LCExtendedFunctionCommandExtended extends ExtendedSourceLinkControlWord
|
||||
{
|
||||
private static final IntField EXTENDED_FUNCTION = IntField.length16(OCTET_1_BIT_8);
|
||||
private static final IntField EXTENDED_FUNCTION_ARGUMENTS = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
|
||||
private Identifier mTargetAddress;
|
||||
private FullyQualifiedRadioIdentifier mSourceAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCExtendedFunctionCommandExtended(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getMessageStub());
|
||||
sb.append(" TO:").append(getTargetAddress());
|
||||
if(hasSourceIDExtension())
|
||||
{
|
||||
sb.append(" FM:").append(getSourceAddress());
|
||||
}
|
||||
sb.append(" ").append(getExtendedFunction());
|
||||
sb.append(" ARGUMENTS:").append(getExtendedFunctionArguments());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Source address. Doesn't use the parent class method since the source address value is not available.
|
||||
*/
|
||||
@Override
|
||||
public FullyQualifiedRadioIdentifier getSourceAddress()
|
||||
{
|
||||
if(mSourceAddress == null && hasSourceIDExtension())
|
||||
{
|
||||
int wacn = getSourceIDExtension().getWACN();
|
||||
int system = getSourceIDExtension().getSystem();
|
||||
int id = getSourceIDExtension().getId();
|
||||
mSourceAddress = APCO25FullyQualifiedRadioIdentifier.createFrom(id, wacn, system, id);
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates the type of extended function
|
||||
*/
|
||||
public ExtendedFunction getExtendedFunction()
|
||||
{
|
||||
return ExtendedFunction.fromValue(getInt(EXTENDED_FUNCTION));
|
||||
}
|
||||
|
||||
/**
|
||||
* Argument(s). May not be required for the class/function and will be set to null (0) if not required.
|
||||
*/
|
||||
public String getExtendedFunctionArguments()
|
||||
{
|
||||
return getMessage().getHex(EXTENDED_FUNCTION_ARGUMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup address
|
||||
*/
|
||||
public Identifier getTargetAddress()
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of identifiers contained in this message
|
||||
*/
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getTargetAddress());
|
||||
if(hasSourceIDExtension())
|
||||
{
|
||||
mIdentifiers.add(getSourceAddress());
|
||||
}
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,39 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Current user of an APCO25 channel on both inbound and outbound channels
|
||||
* Group affiliation query
|
||||
*/
|
||||
public class LCGroupAffiliationQuery extends LinkControlWord
|
||||
{
|
||||
private static final int[] TARGET_ADDRESS = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
42, 43, 44, 45, 46, 47};
|
||||
private static final int[] SOURCE_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private Identifier mTargetAddress;
|
||||
private Identifier mSourceAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -49,7 +43,7 @@ public class LCGroupAffiliationQuery extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCGroupAffiliationQuery(BinaryMessage message)
|
||||
public LCGroupAffiliationQuery(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -70,7 +64,7 @@ public class LCGroupAffiliationQuery extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
@@ -83,7 +77,7 @@ public class LCGroupAffiliationQuery extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
@@ -1,52 +1,49 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Update detailing other users/channels that are active on the network.
|
||||
* Group voice channel update
|
||||
*/
|
||||
public class LCGroupVoiceChannelUpdate extends LinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
public static final int[] FREQUENCY_BAND_A = {8, 9, 10, 11};
|
||||
public static final int[] CHANNEL_A = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
|
||||
public static final int[] GROUP_ADDRESS_A = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||
public static final int[] FREQUENCY_BAND_B = {40, 41, 42, 43};
|
||||
public static final int[] CHANNEL_B = {44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55};
|
||||
public static final int[] GROUP_ADDRESS_B = {56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField FREQUENCY_BAND_A = IntField.length4(OCTET_1_BIT_8);
|
||||
private static final IntField CHANNEL_A = IntField.length12(OCTET_1_BIT_8 + 4);
|
||||
private static final IntField GROUP_ADDRESS_A = IntField.length16(OCTET_3_BIT_24);
|
||||
private static final IntField FREQUENCY_BAND_B = IntField.length4(OCTET_5_BIT_40);
|
||||
private static final IntField CHANNEL_B = IntField.length12(OCTET_5_BIT_40 + 4);
|
||||
private static final IntField GROUP_ADDRESS_B = IntField.length16(OCTET_7_BIT_56);
|
||||
|
||||
private IChannelDescriptor mChannelA;
|
||||
private IChannelDescriptor mChannelB;
|
||||
private APCO25Channel mChannelA;
|
||||
private APCO25Channel mChannelB;
|
||||
private Identifier mTalkgroupA;
|
||||
private Identifier mTalkgroupB;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -54,7 +51,7 @@ public class LCGroupVoiceChannelUpdate extends LinkControlWord implements IFrequ
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*/
|
||||
public LCGroupVoiceChannelUpdate(BinaryMessage message)
|
||||
public LCGroupVoiceChannelUpdate(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -92,21 +89,21 @@ public class LCGroupVoiceChannelUpdate extends LinkControlWord implements IFrequ
|
||||
return mIdentifiers;
|
||||
}
|
||||
|
||||
public IChannelDescriptor getChannelA()
|
||||
public APCO25Channel getChannelA()
|
||||
{
|
||||
if(mChannelA == null)
|
||||
{
|
||||
mChannelA = APCO25Channel.create(getMessage().getInt(FREQUENCY_BAND_A), getMessage().getInt(CHANNEL_A));
|
||||
mChannelA = APCO25Channel.create(getInt(FREQUENCY_BAND_A), getInt(CHANNEL_A));
|
||||
}
|
||||
|
||||
return mChannelA;
|
||||
}
|
||||
|
||||
public IChannelDescriptor getChannelB()
|
||||
public APCO25Channel getChannelB()
|
||||
{
|
||||
if(mChannelB == null)
|
||||
{
|
||||
mChannelB = APCO25Channel.create(getMessage().getInt(FREQUENCY_BAND_B), getMessage().getInt(CHANNEL_B));
|
||||
mChannelB = APCO25Channel.create(getInt(FREQUENCY_BAND_B), getInt(CHANNEL_B));
|
||||
}
|
||||
|
||||
return mChannelB;
|
||||
@@ -114,14 +111,14 @@ public class LCGroupVoiceChannelUpdate extends LinkControlWord implements IFrequ
|
||||
|
||||
public boolean hasChannelB()
|
||||
{
|
||||
return getMessage().getInt(CHANNEL_B) != 0 && getMessage().getInt(GROUP_ADDRESS_A) != getMessage().getInt(GROUP_ADDRESS_B);
|
||||
return getInt(CHANNEL_B) != 0 && getInt(GROUP_ADDRESS_A) != getInt(GROUP_ADDRESS_B);
|
||||
}
|
||||
|
||||
public Identifier getGroupAddressA()
|
||||
{
|
||||
if(mTalkgroupA == null)
|
||||
{
|
||||
mTalkgroupA = APCO25Talkgroup.create(getMessage().getInt(GROUP_ADDRESS_A));
|
||||
mTalkgroupA = APCO25Talkgroup.create(getInt(GROUP_ADDRESS_A));
|
||||
}
|
||||
|
||||
return mTalkgroupA;
|
||||
@@ -131,7 +128,7 @@ public class LCGroupVoiceChannelUpdate extends LinkControlWord implements IFrequ
|
||||
{
|
||||
if(mTalkgroupB == null)
|
||||
{
|
||||
mTalkgroupB = APCO25Talkgroup.create(getMessage().getInt(GROUP_ADDRESS_B));
|
||||
mTalkgroupB = APCO25Talkgroup.create(getInt(GROUP_ADDRESS_B));
|
||||
}
|
||||
|
||||
return mTalkgroupB;
|
||||
|
||||
@@ -1,61 +1,55 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25ExplicitChannel;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
|
||||
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.VoiceLinkControlMessage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Update detailing other users/channels that are active on the network.
|
||||
* Group voice channel update explicit
|
||||
*/
|
||||
public class LCGroupVoiceChannelUpdateExplicit extends LinkControlWord implements IFrequencyBandReceiver
|
||||
public class LCGroupVoiceChannelUpdateExplicit extends VoiceLinkControlMessage implements IFrequencyBandReceiver
|
||||
{
|
||||
public static final int[] SERVICE_OPTIONS = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
public static final int[] GROUP_ADDRESS = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||
public static final int[] DOWNLINK_FREQUENCY_BAND = {40, 41, 42, 43};
|
||||
public static final int[] DOWNLINK_CHANNEL = {44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55};
|
||||
public static final int[] UPLINK_FREQUENCY_BAND = {56, 57, 58, 59};
|
||||
public static final int[] UPLINK_CHANNEL = {60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private VoiceServiceOptions mVoiceServiceOptions;
|
||||
private IChannelDescriptor mChannel;
|
||||
private List<IChannelDescriptor> mChannels;
|
||||
private static final IntField GROUP_ADDRESS = IntField.length16(OCTET_3_BIT_24);
|
||||
private static final IntField DOWNLINK_FREQUENCY_BAND = IntField.length4(OCTET_5_BIT_40);
|
||||
private static final IntField DOWNLINK_CHANNEL = IntField.length12(OCTET_5_BIT_40 + 4);
|
||||
private static final IntField UPLINK_FREQUENCY_BAND = IntField.length4(OCTET_7_BIT_56);
|
||||
private static final IntField UPLINK_CHANNEL = IntField.length12(OCTET_7_BIT_56 + 4);
|
||||
private APCO25Channel mChannel;
|
||||
private Identifier mTalkgroup;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*/
|
||||
public LCGroupVoiceChannelUpdateExplicit(BinaryMessage message)
|
||||
public LCGroupVoiceChannelUpdateExplicit(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -66,24 +60,11 @@ public class LCGroupVoiceChannelUpdateExplicit extends LinkControlWord implement
|
||||
sb.append(getMessageStub());
|
||||
sb.append(" TALKGROUP:").append(getGroupAddress());
|
||||
sb.append(" ").append(getChannel());
|
||||
sb.append(" ").append(getVoiceServiceOptions());
|
||||
sb.append(" ").append(getServiceOptions());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Service options for this channel
|
||||
*/
|
||||
public VoiceServiceOptions getVoiceServiceOptions()
|
||||
{
|
||||
if(mVoiceServiceOptions == null)
|
||||
{
|
||||
mVoiceServiceOptions = new VoiceServiceOptions(getMessage().getInt(SERVICE_OPTIONS));
|
||||
}
|
||||
|
||||
return mVoiceServiceOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
@@ -96,13 +77,12 @@ public class LCGroupVoiceChannelUpdateExplicit extends LinkControlWord implement
|
||||
return mIdentifiers;
|
||||
}
|
||||
|
||||
public IChannelDescriptor getChannel()
|
||||
public APCO25Channel getChannel()
|
||||
{
|
||||
if(mChannel == null)
|
||||
{
|
||||
mChannel = APCO25ExplicitChannel.create(getMessage().getInt(DOWNLINK_FREQUENCY_BAND),
|
||||
getMessage().getInt(DOWNLINK_CHANNEL), getMessage().getInt(UPLINK_FREQUENCY_BAND),
|
||||
getMessage().getInt(UPLINK_CHANNEL));
|
||||
mChannel = APCO25ExplicitChannel.create(getInt(DOWNLINK_FREQUENCY_BAND), getInt(DOWNLINK_CHANNEL),
|
||||
getInt(UPLINK_FREQUENCY_BAND), getInt(UPLINK_CHANNEL));
|
||||
}
|
||||
|
||||
return mChannel;
|
||||
@@ -112,7 +92,7 @@ public class LCGroupVoiceChannelUpdateExplicit extends LinkControlWord implement
|
||||
{
|
||||
if(mTalkgroup == null)
|
||||
{
|
||||
mTalkgroup = APCO25Talkgroup.create(getMessage().getInt(GROUP_ADDRESS));
|
||||
mTalkgroup = APCO25Talkgroup.create(getInt(GROUP_ADDRESS));
|
||||
}
|
||||
|
||||
return mTalkgroup;
|
||||
@@ -121,8 +101,6 @@ public class LCGroupVoiceChannelUpdateExplicit extends LinkControlWord implement
|
||||
@Override
|
||||
public List<IChannelDescriptor> getChannels()
|
||||
{
|
||||
List<IChannelDescriptor> channels = new ArrayList<>();
|
||||
channels.add(getChannel());
|
||||
return channels;
|
||||
return Collections.singletonList(getChannel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +1,40 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
|
||||
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.VoiceLinkControlMessage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Current user of an APCO25 channel on both inbound and outbound channels
|
||||
* Group voice channel user.
|
||||
*/
|
||||
public class LCGroupVoiceChannelUser extends LinkControlWord
|
||||
public class LCGroupVoiceChannelUser extends VoiceLinkControlMessage
|
||||
{
|
||||
private static final int[] SERVICE_OPTIONS = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] GROUP_ADDRESS = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] SOURCE_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private VoiceServiceOptions mVoiceServiceOptions;
|
||||
private static final IntField GROUP_ADDRESS = IntField.length16(OCTET_4_BIT_32);
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private Identifier mGroupAddress;
|
||||
private Identifier mSourceAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -52,7 +44,7 @@ public class LCGroupVoiceChannelUser extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCGroupVoiceChannelUser(BinaryMessage message)
|
||||
public LCGroupVoiceChannelUser(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -63,23 +55,10 @@ public class LCGroupVoiceChannelUser extends LinkControlWord
|
||||
sb.append(getMessageStub());
|
||||
sb.append(" FM:").append(getSourceAddress());
|
||||
sb.append(" TO:").append(getGroupAddress());
|
||||
sb.append(" SERVICE OPTIONS:").append(getVoiceServiceOptions());
|
||||
sb.append(" SERVICE OPTIONS:").append(getServiceOptions());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Service Options for this channel
|
||||
*/
|
||||
public VoiceServiceOptions getVoiceServiceOptions()
|
||||
{
|
||||
if(mVoiceServiceOptions == null)
|
||||
{
|
||||
mVoiceServiceOptions = new VoiceServiceOptions(getMessage().getInt(SERVICE_OPTIONS));
|
||||
}
|
||||
|
||||
return mVoiceServiceOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup address
|
||||
*/
|
||||
@@ -87,7 +66,7 @@ public class LCGroupVoiceChannelUser extends LinkControlWord
|
||||
{
|
||||
if(mGroupAddress == null)
|
||||
{
|
||||
mGroupAddress = APCO25Talkgroup.create(getMessage().getInt(GROUP_ADDRESS));
|
||||
mGroupAddress = APCO25Talkgroup.create(getInt(GROUP_ADDRESS));
|
||||
}
|
||||
|
||||
return mGroupAddress;
|
||||
@@ -100,12 +79,20 @@ public class LCGroupVoiceChannelUser extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the source address is valid and non-zero
|
||||
*/
|
||||
public boolean hasSourceAddress()
|
||||
{
|
||||
return getInt(SOURCE_ADDRESS) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of identifiers contained in this message
|
||||
*/
|
||||
@@ -116,7 +103,10 @@ public class LCGroupVoiceChannelUser extends LinkControlWord
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getGroupAddress());
|
||||
mIdentifiers.add(getSourceAddress());
|
||||
if(hasSourceAddress())
|
||||
{
|
||||
mIdentifiers.add(getSourceAddress());
|
||||
}
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
|
||||
@@ -1,46 +1,41 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.message.APCO25ShortDataMessage;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Echo of the status update from a subscriber when the destination of the update is another subscriber unit.
|
||||
* Echo of the short data message from a subscriber when the destination of the update is another subscriber unit.
|
||||
*/
|
||||
public class LCMessageUpdate extends LinkControlWord
|
||||
{
|
||||
private static final int[] MESSAGE = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] TARGET_ADDRESS = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
42, 43, 44, 45, 46, 47};
|
||||
private static final int[] SOURCE_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField MESSAGE = IntField.length16(OCTET_1_BIT_8);
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
|
||||
private Identifier mShortDataMessage;
|
||||
private Identifier mTargetAddress;
|
||||
@@ -52,7 +47,7 @@ public class LCMessageUpdate extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCMessageUpdate(BinaryMessage message)
|
||||
public LCMessageUpdate(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -71,7 +66,7 @@ public class LCMessageUpdate extends LinkControlWord
|
||||
{
|
||||
if(mShortDataMessage == null)
|
||||
{
|
||||
mShortDataMessage = APCO25ShortDataMessage.create(getMessage().getInt(MESSAGE));
|
||||
mShortDataMessage = APCO25ShortDataMessage.create(getInt(MESSAGE));
|
||||
}
|
||||
|
||||
return mShortDataMessage;
|
||||
@@ -84,7 +79,7 @@ public class LCMessageUpdate extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
@@ -97,7 +92,7 @@ public class LCMessageUpdate extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.message.APCO25ShortDataMessage;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.ExtendedSourceLinkControlWord;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Message Update with extended SUID
|
||||
*/
|
||||
public class LCMessageUpdateExtended extends ExtendedSourceLinkControlWord
|
||||
{
|
||||
private static final IntField MESSAGE = IntField.length16(OCTET_1_BIT_8);
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_3_BIT_24);
|
||||
|
||||
private Identifier mShortDataMessage;
|
||||
private Identifier mTargetAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCMessageUpdateExtended(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getMessageStub());
|
||||
sb.append(" TO:").append(getTargetAddress());
|
||||
if(hasSourceIDExtension())
|
||||
{
|
||||
sb.append(" FM:").append(getSourceAddress());
|
||||
}
|
||||
sb.append(" SDM:").append(getShortDataMessage());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Identifier getShortDataMessage()
|
||||
{
|
||||
if(mShortDataMessage == null)
|
||||
{
|
||||
mShortDataMessage = APCO25ShortDataMessage.create(getInt(MESSAGE));
|
||||
}
|
||||
|
||||
return mShortDataMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup address
|
||||
*/
|
||||
public Identifier getTargetAddress()
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of identifiers contained in this message
|
||||
*/
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getTargetAddress());
|
||||
if(hasSourceIDExtension())
|
||||
{
|
||||
mIdentifiers.add(getSourceAddress());
|
||||
}
|
||||
mIdentifiers.add(getShortDataMessage());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,26 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25System;
|
||||
@@ -31,7 +29,6 @@ import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.SystemServiceClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -40,12 +37,11 @@ import java.util.List;
|
||||
*/
|
||||
public class LCNetworkStatusBroadcast extends LinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final int[] RESERVED = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] WACN = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35};
|
||||
private static final int[] SYSTEM = {36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] FREQUENCY_BAND = {48, 49, 50, 51};
|
||||
private static final int[] CHANNEL_NUMBER = {52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
|
||||
private static final int[] SERVICE_CLASS = {64, 65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField WACN = IntField.length20(OCTET_2_BIT_16);
|
||||
private static final IntField SYSTEM = IntField.length12(OCTET_4_BIT_32 + 4);
|
||||
private static final IntField FREQUENCY_BAND = IntField.length4(OCTET_6_BIT_48);
|
||||
private static final IntField CHANNEL_NUMBER = IntField.length12(OCTET_6_BIT_48 + 4);
|
||||
private static final IntField SERVICE_CLASS = IntField.length8(OCTET_8_BIT_64);
|
||||
|
||||
private List<Identifier> mIdentifiers;
|
||||
private Identifier mWACN;
|
||||
@@ -58,7 +54,7 @@ public class LCNetworkStatusBroadcast extends LinkControlWord implements IFreque
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCNetworkStatusBroadcast(BinaryMessage message)
|
||||
public LCNetworkStatusBroadcast(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -78,7 +74,7 @@ public class LCNetworkStatusBroadcast extends LinkControlWord implements IFreque
|
||||
{
|
||||
if(mWACN == null)
|
||||
{
|
||||
mWACN = APCO25Wacn.create(getMessage().getInt(WACN));
|
||||
mWACN = APCO25Wacn.create(getInt(WACN));
|
||||
}
|
||||
|
||||
return mWACN;
|
||||
@@ -88,7 +84,7 @@ public class LCNetworkStatusBroadcast extends LinkControlWord implements IFreque
|
||||
{
|
||||
if(mSystem == null)
|
||||
{
|
||||
mSystem = APCO25System.create(getMessage().getInt(SYSTEM));
|
||||
mSystem = APCO25System.create(getInt(SYSTEM));
|
||||
}
|
||||
|
||||
return mSystem;
|
||||
@@ -98,8 +94,7 @@ public class LCNetworkStatusBroadcast extends LinkControlWord implements IFreque
|
||||
{
|
||||
if(mChannel == null)
|
||||
{
|
||||
mChannel = APCO25Channel.create(getMessage().getInt(FREQUENCY_BAND),
|
||||
getMessage().getInt(CHANNEL_NUMBER));
|
||||
mChannel = APCO25Channel.create(getInt(FREQUENCY_BAND), getInt(CHANNEL_NUMBER));
|
||||
}
|
||||
|
||||
return mChannel;
|
||||
@@ -109,7 +104,7 @@ public class LCNetworkStatusBroadcast extends LinkControlWord implements IFreque
|
||||
{
|
||||
if(mSystemServiceClass == null)
|
||||
{
|
||||
mSystemServiceClass = new SystemServiceClass(getMessage().getInt(SERVICE_CLASS));
|
||||
mSystemServiceClass = new SystemServiceClass(getInt(SERVICE_CLASS));
|
||||
}
|
||||
|
||||
return mSystemServiceClass;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -15,12 +14,13 @@
|
||||
*
|
||||
* 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.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25System;
|
||||
@@ -28,22 +28,21 @@ import io.github.dsheirer.module.decode.p25.identifier.APCO25Wacn;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25ExplicitChannel;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Secondary control channel broadcast information.
|
||||
* Network status broadcast explicit
|
||||
*/
|
||||
public class LCNetworkStatusBroadcastExplicit extends LinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final int[] WACN = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27};
|
||||
private static final int[] SYSTEM = {28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] DOWNLINK_FREQUENCY_BAND = {40, 41, 42, 43};
|
||||
private static final int[] DOWNLINK_CHANNEL_NUMBER = {44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55};
|
||||
private static final int[] UPLINK_FREQUENCY_BAND = {56, 57, 58, 59};
|
||||
private static final int[] UPLINK_CHANNEL_NUMBER = {60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private static final IntField WACN = IntField.length20(OCTET_1_BIT_8);
|
||||
private static final IntField SYSTEM = IntField.length12(OCTET_3_BIT_24 + 4);
|
||||
private static final IntField DOWNLINK_FREQUENCY_BAND = IntField.length4(OCTET_5_BIT_40);
|
||||
private static final IntField DOWNLINK_CHANNEL_NUMBER = IntField.length12(OCTET_5_BIT_40 + 4);
|
||||
private static final IntField UPLINK_FREQUENCY_BAND = IntField.length4(OCTET_7_BIT_56);
|
||||
private static final IntField UPLINK_CHANNEL_NUMBER = IntField.length12(OCTET_7_BIT_56 + 4);
|
||||
private List<Identifier> mIdentifiers;
|
||||
private Identifier mWACN;
|
||||
private Identifier mSystem;
|
||||
@@ -54,7 +53,7 @@ public class LCNetworkStatusBroadcastExplicit extends LinkControlWord implements
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCNetworkStatusBroadcastExplicit(BinaryMessage message)
|
||||
public LCNetworkStatusBroadcastExplicit(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -73,7 +72,7 @@ public class LCNetworkStatusBroadcastExplicit extends LinkControlWord implements
|
||||
{
|
||||
if(mWACN == null)
|
||||
{
|
||||
mWACN = APCO25Wacn.create(getMessage().getInt(WACN));
|
||||
mWACN = APCO25Wacn.create(getInt(WACN));
|
||||
}
|
||||
|
||||
return mWACN;
|
||||
@@ -83,7 +82,7 @@ public class LCNetworkStatusBroadcastExplicit extends LinkControlWord implements
|
||||
{
|
||||
if(mSystem == null)
|
||||
{
|
||||
mSystem = APCO25System.create(getMessage().getInt(SYSTEM));
|
||||
mSystem = APCO25System.create(getInt(SYSTEM));
|
||||
}
|
||||
|
||||
return mSystem;
|
||||
@@ -93,9 +92,8 @@ public class LCNetworkStatusBroadcastExplicit extends LinkControlWord implements
|
||||
{
|
||||
if(mChannel == null)
|
||||
{
|
||||
mChannel = APCO25ExplicitChannel.create(getMessage().getInt(DOWNLINK_FREQUENCY_BAND),
|
||||
getMessage().getInt(DOWNLINK_CHANNEL_NUMBER), getMessage().getInt(UPLINK_FREQUENCY_BAND),
|
||||
getMessage().getInt(UPLINK_CHANNEL_NUMBER));
|
||||
mChannel = APCO25ExplicitChannel.create(getInt(DOWNLINK_FREQUENCY_BAND), getInt(DOWNLINK_CHANNEL_NUMBER),
|
||||
getInt(UPLINK_FREQUENCY_BAND), getInt(UPLINK_CHANNEL_NUMBER));
|
||||
}
|
||||
|
||||
return mChannel;
|
||||
@@ -120,8 +118,6 @@ public class LCNetworkStatusBroadcastExplicit extends LinkControlWord implements
|
||||
@Override
|
||||
public List<IChannelDescriptor> getChannels()
|
||||
{
|
||||
List<IChannelDescriptor> channels = new ArrayList<>();
|
||||
channels.add(getChannel());
|
||||
return channels;
|
||||
return Collections.singletonList(getChannel());
|
||||
}
|
||||
}
|
||||
@@ -1,48 +1,44 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.encryption.EncryptionKeyIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.encryption.APCO25EncryptionKey;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Echo of the status update from a subscriber when the destination of the update is another subscriber unit.
|
||||
* Protection (ie encryption) parameter broadcast.
|
||||
*
|
||||
* Note: this is an obsolete message.
|
||||
*/
|
||||
public class LCProtectionParameterBroadcast extends LinkControlWord
|
||||
{
|
||||
private static final int[] RESERVED = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] ALGORITHM_ID = {24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] KEY_ID = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] TARGET_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private static final IntField ALGORITHM_ID = IntField.length8(OCTET_3_BIT_24);
|
||||
private static final IntField KEY_ID = IntField.length16(OCTET_4_BIT_32);
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private Identifier mEncryptionKey;
|
||||
private Identifier mTargetAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -52,7 +48,7 @@ public class LCProtectionParameterBroadcast extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCProtectionParameterBroadcast(BinaryMessage message)
|
||||
public LCProtectionParameterBroadcast(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -70,8 +66,8 @@ public class LCProtectionParameterBroadcast extends LinkControlWord
|
||||
{
|
||||
if(mEncryptionKey == null)
|
||||
{
|
||||
mEncryptionKey = EncryptionKeyIdentifier.create(APCO25EncryptionKey.create(getMessage().getInt(ALGORITHM_ID),
|
||||
getMessage().getInt(KEY_ID)));
|
||||
mEncryptionKey = EncryptionKeyIdentifier.create(APCO25EncryptionKey.create(getInt(ALGORITHM_ID),
|
||||
getInt(KEY_ID)));
|
||||
}
|
||||
|
||||
return mEncryptionKey;
|
||||
@@ -84,7 +80,7 @@ public class LCProtectionParameterBroadcast extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25Lra;
|
||||
@@ -33,7 +31,6 @@ import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.SystemServiceClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -42,13 +39,13 @@ import java.util.List;
|
||||
*/
|
||||
public class LCRFSSStatusBroadcast extends LinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final int[] LRA = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] SYSTEM = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] RFSS = {32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] SITE = {40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] FREQUENCY_BAND = {48, 49, 50, 51};
|
||||
private static final int[] CHANNEL_NUMBER = {52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
|
||||
private static final int[] SERVICE_CLASS = {64, 65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField LRA = IntField.length8(OCTET_1_BIT_8);
|
||||
private static final IntField SYSTEM = IntField.length12(OCTET_2_BIT_16 + 4);
|
||||
private static final IntField RFSS = IntField.length8(OCTET_4_BIT_32);
|
||||
private static final IntField SITE = IntField.length8(OCTET_5_BIT_40);
|
||||
private static final IntField FREQUENCY_BAND = IntField.length4(OCTET_6_BIT_48);
|
||||
private static final IntField CHANNEL_NUMBER = IntField.length12(OCTET_6_BIT_48 + 4);
|
||||
private static final IntField SERVICE_CLASS = IntField.length8(OCTET_8_BIT_64);
|
||||
|
||||
private List<Identifier> mIdentifiers;
|
||||
private Identifier mLRA;
|
||||
@@ -63,7 +60,7 @@ public class LCRFSSStatusBroadcast extends LinkControlWord implements IFrequency
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCRFSSStatusBroadcast(BinaryMessage message)
|
||||
public LCRFSSStatusBroadcast(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -84,7 +81,7 @@ public class LCRFSSStatusBroadcast extends LinkControlWord implements IFrequency
|
||||
{
|
||||
if(mLRA == null)
|
||||
{
|
||||
mLRA = APCO25Lra.create(getMessage().getInt(LRA));
|
||||
mLRA = APCO25Lra.create(getInt(LRA));
|
||||
}
|
||||
|
||||
return mLRA;
|
||||
@@ -94,7 +91,7 @@ public class LCRFSSStatusBroadcast extends LinkControlWord implements IFrequency
|
||||
{
|
||||
if(mSystem == null)
|
||||
{
|
||||
mSystem = APCO25System.create(getMessage().getInt(SYSTEM));
|
||||
mSystem = APCO25System.create(getInt(SYSTEM));
|
||||
}
|
||||
|
||||
return mSystem;
|
||||
@@ -104,7 +101,7 @@ public class LCRFSSStatusBroadcast extends LinkControlWord implements IFrequency
|
||||
{
|
||||
if(mRFSS == null)
|
||||
{
|
||||
mRFSS = APCO25Rfss.create(getMessage().getInt(RFSS));
|
||||
mRFSS = APCO25Rfss.create(getInt(RFSS));
|
||||
}
|
||||
|
||||
return mRFSS;
|
||||
@@ -114,7 +111,7 @@ public class LCRFSSStatusBroadcast extends LinkControlWord implements IFrequency
|
||||
{
|
||||
if(mSite == null)
|
||||
{
|
||||
mSite = APCO25Site.create(getMessage().getInt(SITE));
|
||||
mSite = APCO25Site.create(getInt(SITE));
|
||||
}
|
||||
|
||||
return mSite;
|
||||
@@ -124,8 +121,7 @@ public class LCRFSSStatusBroadcast extends LinkControlWord implements IFrequency
|
||||
{
|
||||
if(mChannel == null)
|
||||
{
|
||||
mChannel = APCO25Channel.create(getMessage().getInt(FREQUENCY_BAND),
|
||||
getMessage().getInt(CHANNEL_NUMBER));
|
||||
mChannel = APCO25Channel.create(getInt(FREQUENCY_BAND), getInt(CHANNEL_NUMBER));
|
||||
}
|
||||
|
||||
return mChannel;
|
||||
@@ -135,7 +131,7 @@ public class LCRFSSStatusBroadcast extends LinkControlWord implements IFrequency
|
||||
{
|
||||
if(mSystemServiceClass == null)
|
||||
{
|
||||
mSystemServiceClass = new SystemServiceClass(getMessage().getInt(SERVICE_CLASS));
|
||||
mSystemServiceClass = new SystemServiceClass(getInt(SERVICE_CLASS));
|
||||
}
|
||||
|
||||
return mSystemServiceClass;
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25Lra;
|
||||
@@ -32,24 +30,23 @@ import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25ExplicitCha
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.SystemServiceClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Secondary control channel broadcast information.
|
||||
* RFSS Status Broadcast Explicit
|
||||
*/
|
||||
public class LCRFSSStatusBroadcastExplicit extends LinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final int[] LRA = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] UPLINK_FREQUENCY_BAND = {16, 17, 18, 19};
|
||||
private static final int[] UPLINK_CHANNEL_NUMBER = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] RFSS = {32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] SITE = {40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] DOWNLINK_FREQUENCY_BAND = {48, 49, 50, 51};
|
||||
private static final int[] DOWNLINK_CHANNEL_NUMBER = {52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
|
||||
private static final int[] SERVICE_CLASS = {64, 65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private static final IntField LRA = IntField.length8(OCTET_1_BIT_8);
|
||||
private static final IntField UPLINK_FREQUENCY_BAND = IntField.length4(OCTET_2_BIT_16);
|
||||
private static final IntField UPLINK_CHANNEL_NUMBER = IntField.length12(OCTET_2_BIT_16 + 4);
|
||||
private static final IntField RFSS = IntField.length8(OCTET_4_BIT_32);
|
||||
private static final IntField SITE = IntField.length8(OCTET_5_BIT_40);
|
||||
private static final IntField DOWNLINK_FREQUENCY_BAND = IntField.length4(OCTET_6_BIT_48);
|
||||
private static final IntField DOWNLINK_CHANNEL_NUMBER = IntField.length12(OCTET_6_BIT_48 + 4);
|
||||
private static final IntField SERVICE_CLASS = IntField.length8(OCTET_8_BIT_64);
|
||||
private List<Identifier> mIdentifiers;
|
||||
private Identifier mLRA;
|
||||
private Identifier mRFSS;
|
||||
@@ -62,7 +59,7 @@ public class LCRFSSStatusBroadcastExplicit extends LinkControlWord implements IF
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCRFSSStatusBroadcastExplicit(BinaryMessage message)
|
||||
public LCRFSSStatusBroadcastExplicit(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -82,7 +79,7 @@ public class LCRFSSStatusBroadcastExplicit extends LinkControlWord implements IF
|
||||
{
|
||||
if(mLRA == null)
|
||||
{
|
||||
mLRA = APCO25Lra.create(getMessage().getInt(LRA));
|
||||
mLRA = APCO25Lra.create(getInt(LRA));
|
||||
}
|
||||
|
||||
return mLRA;
|
||||
@@ -92,7 +89,7 @@ public class LCRFSSStatusBroadcastExplicit extends LinkControlWord implements IF
|
||||
{
|
||||
if(mRFSS == null)
|
||||
{
|
||||
mRFSS = APCO25Rfss.create(getMessage().getInt(RFSS));
|
||||
mRFSS = APCO25Rfss.create(getInt(RFSS));
|
||||
}
|
||||
|
||||
return mRFSS;
|
||||
@@ -102,7 +99,7 @@ public class LCRFSSStatusBroadcastExplicit extends LinkControlWord implements IF
|
||||
{
|
||||
if(mSite == null)
|
||||
{
|
||||
mSite = APCO25Site.create(getMessage().getInt(SITE));
|
||||
mSite = APCO25Site.create(getInt(SITE));
|
||||
}
|
||||
|
||||
return mSite;
|
||||
@@ -112,9 +109,8 @@ public class LCRFSSStatusBroadcastExplicit extends LinkControlWord implements IF
|
||||
{
|
||||
if(mChannel == null)
|
||||
{
|
||||
mChannel = APCO25ExplicitChannel.create(getMessage().getInt(DOWNLINK_FREQUENCY_BAND),
|
||||
getMessage().getInt(DOWNLINK_CHANNEL_NUMBER), getMessage().getInt(UPLINK_FREQUENCY_BAND),
|
||||
getMessage().getInt(UPLINK_CHANNEL_NUMBER));
|
||||
mChannel = APCO25ExplicitChannel.create(getInt(DOWNLINK_FREQUENCY_BAND), getInt(DOWNLINK_CHANNEL_NUMBER),
|
||||
getInt(UPLINK_FREQUENCY_BAND), getInt(UPLINK_CHANNEL_NUMBER));
|
||||
}
|
||||
|
||||
return mChannel;
|
||||
@@ -124,7 +120,7 @@ public class LCRFSSStatusBroadcastExplicit extends LinkControlWord implements IF
|
||||
{
|
||||
if(mSystemServiceClass == null)
|
||||
{
|
||||
mSystemServiceClass = new SystemServiceClass(getMessage().getInt(SERVICE_CLASS));
|
||||
mSystemServiceClass = new SystemServiceClass(getInt(SERVICE_CLASS));
|
||||
}
|
||||
|
||||
return mSystemServiceClass;
|
||||
@@ -150,8 +146,6 @@ public class LCRFSSStatusBroadcastExplicit extends LinkControlWord implements IF
|
||||
@Override
|
||||
public List<IChannelDescriptor> getChannels()
|
||||
{
|
||||
List<IChannelDescriptor> channels = new ArrayList<>();
|
||||
channels.add(getChannel());
|
||||
return channels;
|
||||
return Collections.singletonList(getChannel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25Rfss;
|
||||
@@ -31,23 +29,22 @@ import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.SystemServiceClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Secondary control channel broadcast information.
|
||||
* Secondary control channel broadcast.
|
||||
*/
|
||||
public class LCSecondaryControlChannelBroadcast extends LinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final int[] RFSS = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] SITE = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] FREQUENCY_BAND_A = {24, 25, 26, 27};
|
||||
private static final int[] CHANNEL_NUMBER_A = {28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] SERVICE_CLASS_A = {40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] FREQUENCY_BAND_B = {48, 49, 50, 51};
|
||||
private static final int[] CHANNEL_NUMBER_B = {52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
|
||||
private static final int[] SERVICE_CLASS_B = {64, 65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField RFSS = IntField.length8(OCTET_1_BIT_8);
|
||||
private static final IntField SITE = IntField.length8(OCTET_2_BIT_16);
|
||||
private static final IntField FREQUENCY_BAND_A = IntField.length4(OCTET_3_BIT_24);
|
||||
private static final IntField CHANNEL_NUMBER_A = IntField.length12(OCTET_3_BIT_24 + 4);
|
||||
private static final IntField SERVICE_CLASS_A = IntField.length8(OCTET_5_BIT_40);
|
||||
private static final IntField FREQUENCY_BAND_B = IntField.length4(OCTET_6_BIT_48);
|
||||
private static final IntField CHANNEL_NUMBER_B = IntField.length12(OCTET_6_BIT_48 + 4);
|
||||
private static final IntField SERVICE_CLASS_B = IntField.length8(OCTET_8_BIT_64);
|
||||
|
||||
private List<Identifier> mIdentifiers;
|
||||
private Identifier mRFSS;
|
||||
@@ -62,7 +59,7 @@ public class LCSecondaryControlChannelBroadcast extends LinkControlWord implemen
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCSecondaryControlChannelBroadcast(BinaryMessage message)
|
||||
public LCSecondaryControlChannelBroadcast(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -87,7 +84,7 @@ public class LCSecondaryControlChannelBroadcast extends LinkControlWord implemen
|
||||
{
|
||||
if(mRFSS == null)
|
||||
{
|
||||
mRFSS = APCO25Rfss.create(getMessage().getInt(RFSS));
|
||||
mRFSS = APCO25Rfss.create(getInt(RFSS));
|
||||
}
|
||||
|
||||
return mRFSS;
|
||||
@@ -97,7 +94,7 @@ public class LCSecondaryControlChannelBroadcast extends LinkControlWord implemen
|
||||
{
|
||||
if(mSite == null)
|
||||
{
|
||||
mSite = APCO25Site.create(getMessage().getInt(SITE));
|
||||
mSite = APCO25Site.create(getInt(SITE));
|
||||
}
|
||||
|
||||
return mSite;
|
||||
@@ -107,8 +104,7 @@ public class LCSecondaryControlChannelBroadcast extends LinkControlWord implemen
|
||||
{
|
||||
if(mChannelA == null)
|
||||
{
|
||||
mChannelA = APCO25Channel.create(getMessage().getInt(FREQUENCY_BAND_A),
|
||||
getMessage().getInt(CHANNEL_NUMBER_A));
|
||||
mChannelA = APCO25Channel.create(getInt(FREQUENCY_BAND_A), getInt(CHANNEL_NUMBER_A));
|
||||
}
|
||||
|
||||
return mChannelA;
|
||||
@@ -116,16 +112,14 @@ public class LCSecondaryControlChannelBroadcast extends LinkControlWord implemen
|
||||
|
||||
private boolean hasChannelB()
|
||||
{
|
||||
return getMessage().getInt(CHANNEL_NUMBER_A) != getMessage().getInt(CHANNEL_NUMBER_B) &&
|
||||
getMessage().getInt(SERVICE_CLASS_B) != 0;
|
||||
return getInt(CHANNEL_NUMBER_A) != getInt(CHANNEL_NUMBER_B) && getInt(SERVICE_CLASS_B) != 0;
|
||||
}
|
||||
|
||||
public IChannelDescriptor getChannelB()
|
||||
{
|
||||
if(mChannelB == null)
|
||||
{
|
||||
mChannelB = APCO25Channel.create(getMessage().getInt(FREQUENCY_BAND_B),
|
||||
getMessage().getInt(CHANNEL_NUMBER_B));
|
||||
mChannelB = APCO25Channel.create(getInt(FREQUENCY_BAND_B), getInt(CHANNEL_NUMBER_B));
|
||||
}
|
||||
|
||||
return mChannelB;
|
||||
@@ -135,7 +129,7 @@ public class LCSecondaryControlChannelBroadcast extends LinkControlWord implemen
|
||||
{
|
||||
if(mSystemServiceClassA == null)
|
||||
{
|
||||
mSystemServiceClassA = new SystemServiceClass(getMessage().getInt(SERVICE_CLASS_A));
|
||||
mSystemServiceClassA = new SystemServiceClass(getInt(SERVICE_CLASS_A));
|
||||
}
|
||||
|
||||
return mSystemServiceClassA;
|
||||
@@ -146,7 +140,7 @@ public class LCSecondaryControlChannelBroadcast extends LinkControlWord implemen
|
||||
{
|
||||
if(mSystemServiceClassB == null)
|
||||
{
|
||||
mSystemServiceClassB = new SystemServiceClass(getMessage().getInt(SERVICE_CLASS_B));
|
||||
mSystemServiceClassB = new SystemServiceClass(getInt(SERVICE_CLASS_B));
|
||||
}
|
||||
|
||||
return mSystemServiceClassB;
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25Rfss;
|
||||
@@ -31,8 +29,8 @@ import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25ExplicitCha
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.SystemServiceClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -40,15 +38,13 @@ import java.util.List;
|
||||
*/
|
||||
public class LCSecondaryControlChannelBroadcastExplicit extends LinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final int[] RFSS = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] SITE = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] DOWNLINK_FREQUENCY_BAND = {24, 25, 26, 27};
|
||||
private static final int[] DOWNLINK_CHANNEL_NUMBER = {28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] UPLINK_FREQUENCY_BAND = {40, 41, 42, 43};
|
||||
private static final int[] UPNLINK_CHANNEL_NUMBER = {44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55};
|
||||
private static final int[] SERVICE_CLASS = {56, 57, 58, 59, 60, 61, 62, 63};
|
||||
private static final int[] RESERVED = {64, 65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private static final IntField RFSS = IntField.length8(OCTET_1_BIT_8);
|
||||
private static final IntField SITE = IntField.length8(OCTET_2_BIT_16);
|
||||
private static final IntField DOWNLINK_FREQUENCY_BAND = IntField.length4(OCTET_3_BIT_24);
|
||||
private static final IntField DOWNLINK_CHANNEL_NUMBER = IntField.length12(OCTET_3_BIT_24 + 4);
|
||||
private static final IntField UPLINK_FREQUENCY_BAND = IntField.length4(OCTET_5_BIT_40);
|
||||
private static final IntField UPNLINK_CHANNEL_NUMBER = IntField.length12(OCTET_5_BIT_40 + 4);
|
||||
private static final IntField SERVICE_CLASS = IntField.length8(OCTET_7_BIT_56);
|
||||
private List<Identifier> mIdentifiers;
|
||||
private Identifier mRFSS;
|
||||
private Identifier mSite;
|
||||
@@ -60,7 +56,7 @@ public class LCSecondaryControlChannelBroadcastExplicit extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCSecondaryControlChannelBroadcastExplicit(BinaryMessage message)
|
||||
public LCSecondaryControlChannelBroadcastExplicit(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -79,7 +75,7 @@ public class LCSecondaryControlChannelBroadcastExplicit extends LinkControlWord
|
||||
{
|
||||
if(mRFSS == null)
|
||||
{
|
||||
mRFSS = APCO25Rfss.create(getMessage().getInt(RFSS));
|
||||
mRFSS = APCO25Rfss.create(getInt(RFSS));
|
||||
}
|
||||
|
||||
return mRFSS;
|
||||
@@ -89,7 +85,7 @@ public class LCSecondaryControlChannelBroadcastExplicit extends LinkControlWord
|
||||
{
|
||||
if(mSite == null)
|
||||
{
|
||||
mSite = APCO25Site.create(getMessage().getInt(SITE));
|
||||
mSite = APCO25Site.create(getInt(SITE));
|
||||
}
|
||||
|
||||
return mSite;
|
||||
@@ -99,9 +95,8 @@ public class LCSecondaryControlChannelBroadcastExplicit extends LinkControlWord
|
||||
{
|
||||
if(mChannel == null)
|
||||
{
|
||||
mChannel = APCO25ExplicitChannel.create(getMessage().getInt(DOWNLINK_FREQUENCY_BAND),
|
||||
getMessage().getInt(DOWNLINK_CHANNEL_NUMBER), getMessage().getInt(UPLINK_FREQUENCY_BAND),
|
||||
getMessage().getInt(UPNLINK_CHANNEL_NUMBER));
|
||||
mChannel = APCO25ExplicitChannel.create(getInt(DOWNLINK_FREQUENCY_BAND), getInt(DOWNLINK_CHANNEL_NUMBER),
|
||||
getInt(UPLINK_FREQUENCY_BAND), getInt(UPNLINK_CHANNEL_NUMBER));
|
||||
}
|
||||
|
||||
return mChannel;
|
||||
@@ -111,7 +106,7 @@ public class LCSecondaryControlChannelBroadcastExplicit extends LinkControlWord
|
||||
{
|
||||
if(mSystemServiceClass == null)
|
||||
{
|
||||
mSystemServiceClass = new SystemServiceClass(getMessage().getInt(SERVICE_CLASS));
|
||||
mSystemServiceClass = new SystemServiceClass(getInt(SERVICE_CLASS));
|
||||
}
|
||||
|
||||
return mSystemServiceClass;
|
||||
@@ -136,8 +131,6 @@ public class LCSecondaryControlChannelBroadcastExplicit extends LinkControlWord
|
||||
@Override
|
||||
public List<IChannelDescriptor> getChannels()
|
||||
{
|
||||
List<IChannelDescriptor> channels = new ArrayList<>();
|
||||
channels.add(getChannel());
|
||||
return channels;
|
||||
return Collections.singletonList(getChannel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Source ID extension word. This is used in conjunction with another link control message to carry a fully qualified
|
||||
* source SUID.
|
||||
*/
|
||||
public class LCSourceIDExtension extends LinkControlWord
|
||||
{
|
||||
private static final IntField SOURCE_SUID_WACN = IntField.length20(OCTET_2_BIT_16);
|
||||
private static final IntField SOURCE_SUID_SYSTEM = IntField.length12(OCTET_4_BIT_32 + 4);
|
||||
private static final IntField SOURCE_SUID_RADIO = IntField.length24(OCTET_6_BIT_48);
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCSourceIDExtension(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getMessageStub());
|
||||
sb.append(" WACN:").append(getWACN());
|
||||
sb.append(" SYSTEM:").append(getSystem());
|
||||
sb.append(" ID:").append(getId());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Source SUID WACN value.
|
||||
*/
|
||||
public int getWACN()
|
||||
{
|
||||
return getInt(SOURCE_SUID_WACN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Source SUID System value.
|
||||
*/
|
||||
public int getSystem()
|
||||
{
|
||||
return getInt(SOURCE_SUID_SYSTEM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Source SUID radio value.
|
||||
*/
|
||||
public int getId()
|
||||
{
|
||||
return getInt(SOURCE_SUID_RADIO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,39 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Current user of an APCO25 channel on both inbound and outbound channels
|
||||
* Status query
|
||||
*/
|
||||
public class LCStatusQuery extends LinkControlWord
|
||||
{
|
||||
private static final int[] TARGET_ADDRESS = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
42, 43, 44, 45, 46, 47};
|
||||
private static final int[] SOURCE_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private Identifier mTargetAddress;
|
||||
private Identifier mSourceAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -49,7 +43,7 @@ public class LCStatusQuery extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCStatusQuery(BinaryMessage message)
|
||||
public LCStatusQuery(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -70,7 +64,7 @@ public class LCStatusQuery extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
@@ -83,7 +77,7 @@ public class LCStatusQuery extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
@@ -1,34 +1,31 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.status.APCO25UnitStatus;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.status.APCO25UserStatus;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -37,12 +34,10 @@ import java.util.List;
|
||||
*/
|
||||
public class LCStatusUpdate extends LinkControlWord
|
||||
{
|
||||
private static final int[] UNIT_STATUS = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] USER_STATUS = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] TARGET_ADDRESS = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
42, 43, 44, 45, 46, 47};
|
||||
private static final int[] SOURCE_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField UNIT_STATUS = IntField.length8(OCTET_1_BIT_8);
|
||||
private static final IntField USER_STATUS = IntField.length8(OCTET_2_BIT_16);
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
|
||||
private Identifier mUnitStatus;
|
||||
private Identifier mUserStatus;
|
||||
@@ -55,7 +50,7 @@ public class LCStatusUpdate extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCStatusUpdate(BinaryMessage message)
|
||||
public LCStatusUpdate(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.status.APCO25UnitStatus;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.status.APCO25UserStatus;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.ExtendedSourceLinkControlWord;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Status Update with extended SUID
|
||||
*/
|
||||
public class LCStatusUpdateExtended extends ExtendedSourceLinkControlWord
|
||||
{
|
||||
private static final IntField UNIT_STATUS = IntField.length8(OCTET_1_BIT_8);
|
||||
private static final IntField USER_STATUS = IntField.length8(OCTET_2_BIT_16);
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_3_BIT_24);
|
||||
|
||||
private Identifier mUnitStatus;
|
||||
private Identifier mUserStatus;
|
||||
private Identifier mTargetAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCStatusUpdateExtended(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getMessageStub());
|
||||
sb.append(" TO:").append(getTargetAddress());
|
||||
if(hasSourceIDExtension())
|
||||
{
|
||||
sb.append(" FM:").append(getSourceAddress());
|
||||
}
|
||||
sb.append(" UNIT:").append(getUnitStatus());
|
||||
sb.append(" USER:").append(getUserStatus());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Identifier getUnitStatus()
|
||||
{
|
||||
if(mUnitStatus == null)
|
||||
{
|
||||
mUnitStatus = APCO25UnitStatus.create(getMessage().getInt(UNIT_STATUS));
|
||||
}
|
||||
|
||||
return mUnitStatus;
|
||||
}
|
||||
|
||||
public Identifier getUserStatus()
|
||||
{
|
||||
if(mUserStatus == null)
|
||||
{
|
||||
mUserStatus = APCO25UserStatus.create(getMessage().getInt(USER_STATUS));
|
||||
}
|
||||
|
||||
return mUserStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup address
|
||||
*/
|
||||
public Identifier getTargetAddress()
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of identifiers contained in this message
|
||||
*/
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getTargetAddress());
|
||||
if(hasSourceIDExtension())
|
||||
{
|
||||
mIdentifiers.add(getSourceAddress());
|
||||
}
|
||||
mIdentifiers.add(getUnitStatus());
|
||||
mIdentifiers.add(getUserStatus());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
@@ -15,16 +14,16 @@
|
||||
*
|
||||
* 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.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -33,18 +32,16 @@ import java.util.List;
|
||||
*/
|
||||
public class LCSystemServiceBroadcast extends LinkControlWord
|
||||
{
|
||||
private static final int[] REQUEST_PRIORITY_LEVEL = {20, 21, 22, 23};
|
||||
private static final int[] AVAILABLE_SERVICES = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
|
||||
45, 46, 47};
|
||||
private static final int[] SUPPORTED_SERVICES = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||
62, 63, 64, 65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField REQUEST_PRIORITY_LEVEL = IntField.length4(OCTET_2_BIT_16 + 4);
|
||||
private static final IntField AVAILABLE_SERVICES = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField SUPPORTED_SERVICES = IntField.length24(OCTET_6_BIT_48);
|
||||
|
||||
/**
|
||||
* Constructs a Link Control Word from the binary message sequence.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCSystemServiceBroadcast(BinaryMessage message)
|
||||
public LCSystemServiceBroadcast(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -64,20 +61,18 @@ public class LCSystemServiceBroadcast extends LinkControlWord
|
||||
*/
|
||||
public int getRequestPriorityLevel()
|
||||
{
|
||||
return getMessage().getInt(REQUEST_PRIORITY_LEVEL);
|
||||
return getInt(REQUEST_PRIORITY_LEVEL);
|
||||
}
|
||||
|
||||
|
||||
public List<Service> getAvailableServices()
|
||||
{
|
||||
long bitmap = getMessage().getLong(AVAILABLE_SERVICES);
|
||||
return Service.getServices(bitmap);
|
||||
return Service.getServices(getInt(AVAILABLE_SERVICES));
|
||||
}
|
||||
|
||||
public List<Service> getSupportedServices()
|
||||
{
|
||||
long bitmap = getMessage().getLong(SUPPORTED_SERVICES);
|
||||
return Service.getServices(bitmap);
|
||||
return Service.getServices(getInt(SUPPORTED_SERVICES));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,34 +1,31 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.telephone.APCO25TelephoneNumber;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.Digit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -37,18 +34,17 @@ import java.util.List;
|
||||
*/
|
||||
public class LCTelephoneInterconnectAnswerRequest extends LinkControlWord
|
||||
{
|
||||
private static final int[] DIGIT_1 = {8, 9, 10, 11};
|
||||
private static final int[] DIGIT_2 = {12, 13, 14, 15};
|
||||
private static final int[] DIGIT_3 = {16, 17, 18, 19};
|
||||
private static final int[] DIGIT_4 = {20, 21, 22, 23};
|
||||
private static final int[] DIGIT_5 = {24, 25, 26, 27};
|
||||
private static final int[] DIGIT_6 = {28, 29, 30, 31};
|
||||
private static final int[] DIGIT_7 = {32, 33, 34, 35};
|
||||
private static final int[] DIGIT_8 = {36, 37, 38, 39};
|
||||
private static final int[] DIGIT_9 = {40, 41, 42, 43};
|
||||
private static final int[] DIGIT_10 = {44, 45, 46, 47};
|
||||
private static final int[] TARGET_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
private static final IntField DIGIT_1 = IntField.length4(OCTET_1_BIT_8);
|
||||
private static final IntField DIGIT_2 = IntField.length4(OCTET_1_BIT_8 + 4);
|
||||
private static final IntField DIGIT_3 = IntField.length4(OCTET_2_BIT_16);
|
||||
private static final IntField DIGIT_4 = IntField.length4(OCTET_2_BIT_16 + 4);
|
||||
private static final IntField DIGIT_5 = IntField.length4(OCTET_3_BIT_24);
|
||||
private static final IntField DIGIT_6 = IntField.length4(OCTET_3_BIT_24 + 4);
|
||||
private static final IntField DIGIT_7 = IntField.length4(OCTET_4_BIT_32);
|
||||
private static final IntField DIGIT_8 = IntField.length4(OCTET_4_BIT_32 + 4);
|
||||
private static final IntField DIGIT_9 = IntField.length4(OCTET_5_BIT_40);
|
||||
private static final IntField DIGIT_10 = IntField.length4(OCTET_5_BIT_40 + 4);
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
|
||||
private Identifier mTargetAddress;
|
||||
private Identifier mTelephoneNumber;
|
||||
@@ -59,7 +55,7 @@ public class LCTelephoneInterconnectAnswerRequest extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCTelephoneInterconnectAnswerRequest(BinaryMessage message)
|
||||
public LCTelephoneInterconnectAnswerRequest(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -79,16 +75,16 @@ public class LCTelephoneInterconnectAnswerRequest extends LinkControlWord
|
||||
if(mTelephoneNumber == null)
|
||||
{
|
||||
List<Integer> digits = new ArrayList<>();
|
||||
digits.add(getMessage().getInt(DIGIT_1));
|
||||
digits.add(getMessage().getInt(DIGIT_2));
|
||||
digits.add(getMessage().getInt(DIGIT_3));
|
||||
digits.add(getMessage().getInt(DIGIT_4));
|
||||
digits.add(getMessage().getInt(DIGIT_5));
|
||||
digits.add(getMessage().getInt(DIGIT_6));
|
||||
digits.add(getMessage().getInt(DIGIT_7));
|
||||
digits.add(getMessage().getInt(DIGIT_8));
|
||||
digits.add(getMessage().getInt(DIGIT_9));
|
||||
digits.add(getMessage().getInt(DIGIT_10));
|
||||
digits.add(getInt(DIGIT_1));
|
||||
digits.add(getInt(DIGIT_2));
|
||||
digits.add(getInt(DIGIT_3));
|
||||
digits.add(getInt(DIGIT_4));
|
||||
digits.add(getInt(DIGIT_5));
|
||||
digits.add(getInt(DIGIT_6));
|
||||
digits.add(getInt(DIGIT_7));
|
||||
digits.add(getInt(DIGIT_8));
|
||||
digits.add(getInt(DIGIT_9));
|
||||
digits.add(getInt(DIGIT_10));
|
||||
|
||||
mTelephoneNumber = APCO25TelephoneNumber.createFrom(Digit.decode(digits));
|
||||
}
|
||||
@@ -103,7 +99,7 @@ public class LCTelephoneInterconnectAnswerRequest extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
|
||||
@@ -1,49 +1,39 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.VoiceLinkControlMessage;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Current user of an APCO25 channel on both inbound and outbound channels
|
||||
* Telephone interconnect voice channel user
|
||||
*/
|
||||
public class LCTelephoneInterconnectVoiceChannelUser extends LinkControlWord
|
||||
public class LCTelephoneInterconnectVoiceChannelUser extends VoiceLinkControlMessage
|
||||
{
|
||||
private static final int[] RESERVED_1 = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] SERVICE_OPTIONS = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] RESERVED_2 = {24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] CALL_TIMER = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private VoiceServiceOptions mVoiceServiceOptions;
|
||||
private static final IntField CALL_TIMER = IntField.length16(OCTET_4_BIT_32);
|
||||
private static final IntField ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private Identifier mAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
@@ -52,7 +42,7 @@ public class LCTelephoneInterconnectVoiceChannelUser extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCTelephoneInterconnectVoiceChannelUser(BinaryMessage message)
|
||||
public LCTelephoneInterconnectVoiceChannelUser(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -63,31 +53,18 @@ public class LCTelephoneInterconnectVoiceChannelUser extends LinkControlWord
|
||||
sb.append(getMessageStub());
|
||||
sb.append(" ID:").append(getAddress());
|
||||
sb.append(" CALL TIMER:").append(getCallTimerDuration()).append("MS");
|
||||
sb.append(" ").append(getVoiceServiceOptions());
|
||||
sb.append(" ").append(getServiceOptions());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Service Options for this channel
|
||||
*/
|
||||
public VoiceServiceOptions getVoiceServiceOptions()
|
||||
{
|
||||
if(mVoiceServiceOptions == null)
|
||||
{
|
||||
mVoiceServiceOptions = new VoiceServiceOptions(getMessage().getInt(SERVICE_OPTIONS));
|
||||
}
|
||||
|
||||
return mVoiceServiceOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call timer duration in milliseconds.
|
||||
*/
|
||||
public long getCallTimerDuration()
|
||||
{
|
||||
//Convert from 100 millisecond intervals to milliseconds.
|
||||
return getMessage().getInt(CALL_TIMER) * 100;
|
||||
return getInt(CALL_TIMER) * 100;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +74,7 @@ public class LCTelephoneInterconnectVoiceChannelUser extends LinkControlWord
|
||||
{
|
||||
if(mAddress == null)
|
||||
{
|
||||
mAddress = APCO25Talkgroup.create(getMessage().getInt(ADDRESS));
|
||||
mAddress = APCO25Talkgroup.create(getInt(ADDRESS));
|
||||
}
|
||||
|
||||
return mAddress;
|
||||
@@ -111,8 +88,7 @@ public class LCTelephoneInterconnectVoiceChannelUser extends LinkControlWord
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getAddress());
|
||||
mIdentifiers = Collections.singletonList(getAddress());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
|
||||
@@ -1,34 +1,30 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25System;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25Wacn;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -53,7 +49,7 @@ public class LCUnitAuthenticationCommand extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCUnitAuthenticationCommand(BinaryMessage message)
|
||||
public LCUnitAuthenticationCommand(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
@@ -1,51 +1,43 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25System;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.APCO25Wacn;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.identifier.radio.FullyQualifiedRadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25FullyQualifiedRadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Unit registration command
|
||||
* Note: this message is obsolete as of TIA-102.AABF-A-1
|
||||
*/
|
||||
public class LCUnitRegistrationCommand extends LinkControlWord
|
||||
{
|
||||
private static final int[] WACN = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27};
|
||||
private static final int[] SYSTEM_ID = {28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] TARGET_ADDRESS = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
||||
57, 58, 59, 60, 61, 62, 63};
|
||||
private static final int[] RESERVED = {64, 65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private Identifier mWACN;
|
||||
private Identifier mSystem;
|
||||
private Identifier mTargetAddress;
|
||||
private static final IntField WACN = IntField.length20(OCTET_1_BIT_8);
|
||||
private static final IntField SYSTEM_ID = IntField.length12(OCTET_3_BIT_24 + 4);
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_5_BIT_40);
|
||||
private FullyQualifiedRadioIdentifier mTargetAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
/**
|
||||
@@ -53,7 +45,7 @@ public class LCUnitRegistrationCommand extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCUnitRegistrationCommand(BinaryMessage message)
|
||||
public LCUnitRegistrationCommand(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -62,46 +54,22 @@ public class LCUnitRegistrationCommand extends LinkControlWord
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getMessageStub());
|
||||
sb.append(" WACN:").append(getWACN());
|
||||
sb.append(" SYSTEM:").append(getSystem());
|
||||
sb.append(" RADIO:").append(getTargetAddress());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* WACN
|
||||
* Target address
|
||||
*/
|
||||
public Identifier getWACN()
|
||||
{
|
||||
if(mWACN == null)
|
||||
{
|
||||
mWACN = APCO25Wacn.create(getMessage().getInt(WACN));
|
||||
}
|
||||
|
||||
return mWACN;
|
||||
}
|
||||
|
||||
/**
|
||||
* System
|
||||
*/
|
||||
public Identifier getSystem()
|
||||
{
|
||||
if(mSystem == null)
|
||||
{
|
||||
mSystem = APCO25System.create(getMessage().getInt(SYSTEM_ID));
|
||||
}
|
||||
|
||||
return mSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source address
|
||||
*/
|
||||
public Identifier getTargetAddress()
|
||||
public FullyQualifiedRadioIdentifier getTargetAddress()
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
//No persona ... reuse the radio ID.
|
||||
int wacn = getInt(WACN);
|
||||
int system = getInt(SYSTEM_ID);
|
||||
int radio = getInt(TARGET_ADDRESS);
|
||||
mTargetAddress = APCO25FullyQualifiedRadioIdentifier.createTo(radio, wacn, system, radio);
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
@@ -115,10 +83,7 @@ public class LCUnitRegistrationCommand extends LinkControlWord
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getWACN());
|
||||
mIdentifiers.add(getSystem());
|
||||
mIdentifiers.add(getTargetAddress());
|
||||
mIdentifiers = Collections.singletonList(getTargetAddress());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
|
||||
@@ -1,49 +1,39 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
|
||||
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.VoiceLinkControlMessage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Current user of an APCO25 channel on both inbound and outbound channels
|
||||
* Unit to unit answer request
|
||||
*/
|
||||
public class LCUnitToUnitAnswerRequest extends LinkControlWord
|
||||
public class LCUnitToUnitAnswerRequest extends VoiceLinkControlMessage
|
||||
{
|
||||
private static final int[] SERVICE_OPTIONS = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] RESERVED = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] TARGET_ADDRESS = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
|
||||
44, 45, 46, 47};
|
||||
private static final int[] SOURCE_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private VoiceServiceOptions mVoiceServiceOptions;
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private Identifier mTargetAddress;
|
||||
private Identifier mSourceAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -53,7 +43,7 @@ public class LCUnitToUnitAnswerRequest extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCUnitToUnitAnswerRequest(BinaryMessage message)
|
||||
public LCUnitToUnitAnswerRequest(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -64,23 +54,10 @@ public class LCUnitToUnitAnswerRequest extends LinkControlWord
|
||||
sb.append(getMessageStub());
|
||||
sb.append(" TO:").append(getTargetAddress());
|
||||
sb.append(" FM:").append(getSourceAddress());
|
||||
sb.append(" ").append(getVoiceServiceOptions());
|
||||
sb.append(" ").append(getServiceOptions());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Service Options for this channel
|
||||
*/
|
||||
public VoiceServiceOptions getVoiceServiceOptions()
|
||||
{
|
||||
if(mVoiceServiceOptions == null)
|
||||
{
|
||||
mVoiceServiceOptions = new VoiceServiceOptions(getMessage().getInt(SERVICE_OPTIONS));
|
||||
}
|
||||
|
||||
return mVoiceServiceOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup address
|
||||
*/
|
||||
@@ -88,7 +65,7 @@ public class LCUnitToUnitAnswerRequest extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
@@ -101,7 +78,7 @@ public class LCUnitToUnitAnswerRequest extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
@@ -1,48 +1,39 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 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.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.bits.IntField;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
|
||||
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.VoiceLinkControlMessage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Current user of an APCO25 channel on both inbound and outbound channels
|
||||
* Unit to Unit voice channel user
|
||||
*/
|
||||
public class LCUnitToUnitVoiceChannelUser extends LinkControlWord
|
||||
public class LCUnitToUnitVoiceChannelUser extends VoiceLinkControlMessage
|
||||
{
|
||||
private static final int[] SERVICE_OPTIONS = {16, 17, 18, 19, 20, 21, 22, 23};
|
||||
private static final int[] TARGET_ADDRESS = {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
|
||||
44, 45, 46, 47};
|
||||
private static final int[] SOURCE_ADDRESS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private VoiceServiceOptions mVoiceServiceOptions;
|
||||
private static final IntField TARGET_ADDRESS = IntField.length24(OCTET_3_BIT_24);
|
||||
private static final IntField SOURCE_ADDRESS = IntField.length24(OCTET_6_BIT_48);
|
||||
private Identifier mTargetAddress;
|
||||
private Identifier mSourceAddress;
|
||||
private List<Identifier> mIdentifiers;
|
||||
@@ -52,7 +43,7 @@ public class LCUnitToUnitVoiceChannelUser extends LinkControlWord
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public LCUnitToUnitVoiceChannelUser(BinaryMessage message)
|
||||
public LCUnitToUnitVoiceChannelUser(CorrectedBinaryMessage message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -63,23 +54,10 @@ public class LCUnitToUnitVoiceChannelUser extends LinkControlWord
|
||||
sb.append(getMessageStub());
|
||||
sb.append(" TO:").append(getTargetAddress());
|
||||
sb.append(" FM:").append(getSourceAddress());
|
||||
sb.append(" ").append(getVoiceServiceOptions());
|
||||
sb.append(" ").append(getServiceOptions());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Service Options for this channel
|
||||
*/
|
||||
public VoiceServiceOptions getVoiceServiceOptions()
|
||||
{
|
||||
if(mVoiceServiceOptions == null)
|
||||
{
|
||||
mVoiceServiceOptions = new VoiceServiceOptions(getMessage().getInt(SERVICE_OPTIONS));
|
||||
}
|
||||
|
||||
return mVoiceServiceOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup address
|
||||
*/
|
||||
@@ -87,7 +65,7 @@ public class LCUnitToUnitVoiceChannelUser extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
@@ -100,7 +78,7 @@ public class LCUnitToUnitVoiceChannelUser extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user