Resolves #685. Resolves several issues with P25 Phase 2 channel state and call handling. (#686)

Co-authored-by: Denny <denny@denny-desktop>
This commit is contained in:
Denny Sheirer
2020-03-21 18:31:26 +00:00
committed by GitHub
parent 1bc462b300
commit fd72f459f9
35 changed files with 263 additions and 165 deletions

View File

@@ -85,6 +85,10 @@ public class P25P2AudioModule extends AmbeAudioModule implements IdentifierUpdat
return mSquelchStateListener;
}
/**
* Resets this audio module upon completion of an audio call to prepare for the next call. This method is
* controlled by the squelch state listener and squelch state is controlled by the P25P2DecoderState.
*/
@Override
public void reset()
{
@@ -93,6 +97,10 @@ public class P25P2AudioModule extends AmbeAudioModule implements IdentifierUpdat
mKnoxMetadataProcessor = null;
mToneMetadataProcessor = null;
mQueuedAudioTimeslots.clear();
//Reset encrypted call handling flags
mEncryptedCallStateEstablished = false;
mEncryptedCall = false;
}
@Override
@@ -307,6 +315,7 @@ public class P25P2AudioModule extends AmbeAudioModule implements IdentifierUpdat
public List<String> process(String value)
{
mLog.debug("Processing AMBE Tone Metadata Value: " + value);
if(value != null)
{
if(mLastInput != null && mLastInput.equalsIgnoreCase(value))

View File

@@ -21,33 +21,51 @@
*/
package io.github.dsheirer.module.decode.p25.phase1;
import io.github.dsheirer.alias.Alias;
import io.github.dsheirer.alias.AliasList;
import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.alias.id.record.Record;
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
import io.github.dsheirer.bits.BitSetFullException;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.controller.channel.Channel;
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.IMessageProvider;
import io.github.dsheirer.message.Message;
import io.github.dsheirer.message.MessageProviderModule;
import io.github.dsheirer.message.StuffBitsMessage;
import io.github.dsheirer.message.SyncLossMessage;
import io.github.dsheirer.module.ProcessingChain;
import io.github.dsheirer.module.decode.DecoderType;
import io.github.dsheirer.module.decode.p25.audio.P25P1AudioModule;
import io.github.dsheirer.module.decode.p25.audio.P25P2AudioModule;
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.pdu.PDUMessageFactory;
import io.github.dsheirer.module.decode.p25.phase1.message.pdu.PDUSequence;
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.TSBKMessage;
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.TSBKMessageFactory;
import io.github.dsheirer.module.decode.p25.phase2.DecodeConfigP25Phase2;
import io.github.dsheirer.module.decode.p25.phase2.P25P2DecoderState;
import io.github.dsheirer.module.decode.p25.phase2.P25P2MessageFramer;
import io.github.dsheirer.module.decode.p25.phase2.P25P2MessageProcessor;
import io.github.dsheirer.module.decode.p25.phase2.enumeration.ScrambleParameters;
import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.protocol.Protocol;
import io.github.dsheirer.record.AudioRecordingManager;
import io.github.dsheirer.record.binary.BinaryReader;
import io.github.dsheirer.sample.Broadcaster;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.ReusableByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -440,84 +458,93 @@ public class P25P1MessageFramer implements Listener<Dibit>, IP25P1DataUnitDetect
public static void main(String[] args)
{
Path directory = Paths.get("/media/denny/500G1EXT4/RadioRecordings/Harris APCO25 Phase II");
Path directory = Paths.get("/home/denny/temp/Harris P25-2 Logs/bits");
// Path directory = Paths.get("/media/denny/500G1EXT4/PBITRecordings");
final boolean phase1 = false;
UserPreferences userPreferences = new UserPreferences();
Channel channel = new Channel("Phase 1 Test");
channel.setDecodeConfiguration(new DecodeConfigP25Phase1());
AliasList aliasList = new AliasList("Test Alias List");
Alias alias = new Alias("TG Range 1-65535");
alias.addAliasID(new Record());
alias.addAliasID(new TalkgroupRange(Protocol.APCO25, 1, 65535));
aliasList.addAlias(alias);
AudioRecordingManager recordingManager = new AudioRecordingManager(userPreferences);
recordingManager.start();
ProcessingChain processingChain = new ProcessingChain(channel, new AliasModel());
try
processingChain.addAudioSegmentListener(recordingManager);
processingChain.addModule(new P25P1DecoderState(channel));
processingChain.addModule(new P25P1AudioModule(userPreferences, aliasList));
MessageProviderModule messageProviderModule = new MessageProviderModule();
processingChain.addModule(messageProviderModule);
try(OutputStream logOutput = Files.newOutputStream(directory.resolve("log.txt")))
{
DirectoryStream<Path> stream = Files.newDirectoryStream(directory, "*Hills*TRAFFIC.bits");
try
{
DirectoryStream<Path> stream = Files.newDirectoryStream(directory, "*PHASE1_Hills*TRAFFIC.bits");
stream.forEach(new Consumer<Path>()
{
@Override
public void accept(Path path)
{
mLog.debug("Processing:" + path.toString());
if(phase1)
{
P25P1MessageFramer messageFramer = new P25P1MessageFramer(null, DecoderType.P25_PHASE1.getProtocol().getBitRate());
P25P1MessageProcessor messageProcessor = new P25P1MessageProcessor();
messageFramer.setListener(messageProcessor);
messageProcessor.setMessageListener(new Listener<IMessage>()
{
@Override
public void receive(IMessage message)
stream.forEach(new Consumer<Path>()
{
if(!(message instanceof StuffBitsMessage))
@Override
public void accept(Path path)
{
mLog.debug(message.toString());
mLog.debug("Processing:" + path.toString());
try
{
logOutput.write(("Processing:" + path.toString() + "\n").getBytes());
}
catch(IOException ioe)
{
mLog.error("Error", ioe);
}
P25P1MessageFramer messageFramer = new P25P1MessageFramer(null, DecoderType.P25_PHASE1.getProtocol().getBitRate());
P25P1MessageProcessor messageProcessor = new P25P1MessageProcessor();
messageFramer.setListener(messageProcessor);
messageProcessor.setMessageListener(new Listener<IMessage>()
{
@Override
public void receive(IMessage message)
{
if(!(message instanceof StuffBitsMessage))
{
messageProviderModule.receive(message);
try
{
logOutput.write(message.toString().getBytes());
logOutput.write("\n".getBytes());
}
catch(IOException ioe)
{
mLog.error("Error", ioe);
}
mLog.debug(message.toString());
}
}
});
try(BinaryReader reader = new BinaryReader(path, 200))
{
while(reader.hasNext())
{
ReusableByteBuffer buffer = reader.next();
messageFramer.receive(buffer);
}
}
catch(Exception ioe)
{
ioe.printStackTrace();
}
}
}
});
try(BinaryReader reader = new BinaryReader(path, 200))
{
while(reader.hasNext())
{
ReusableByteBuffer buffer = reader.next();
messageFramer.receive(buffer);
}
}
catch(Exception ioe)
{
ioe.printStackTrace();
}
}
else
{
P25P2MessageFramer messageFramer = new P25P2MessageFramer(null, DecoderType.P25_PHASE2.getProtocol().getBitRate());
ScrambleParameters scrambleParameters = new ScrambleParameters(123654, 813, 10); //Hills County
messageFramer.setScrambleParameters(scrambleParameters);
P25P2MessageProcessor messageProcessor = new P25P2MessageProcessor();
messageFramer.setListener(messageProcessor);
messageProcessor.setMessageListener(new Listener<IMessage>()
{
@Override
public void receive(IMessage message)
{
mLog.debug(message.toString());
}
});
try(BinaryReader reader = new BinaryReader(path, 200))
{
while(reader.hasNext())
{
ReusableByteBuffer buffer = reader.next();
messageFramer.receive(buffer);
}
}
catch(Exception ioe)
{
ioe.printStackTrace();
}
}
}
}
);
);
}
catch(IOException ioe)
{
mLog.error("Error", ioe);
}
}
catch(IOException ioe)
{

View File

@@ -35,7 +35,9 @@ import java.util.List;
*/
public class LCCallTermination extends LinkControlWord
{
private static final int SYSTEM_CONTROLLER = 0xFFFFFD;
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};
@@ -78,7 +80,8 @@ public class LCCallTermination extends LinkControlWord
*/
public boolean isNetworkCommandedTeardown()
{
return getMessage().getInt(ADDRESS) == SYSTEM_CONTROLLER;
int address = getMessage().getInt(ADDRESS);
return address == MOTOROLA_SYSTEM_CONTROLLER || address == HARRIS_SYSTEM_CONTROLLER;
}
/**

View File

@@ -42,6 +42,7 @@ import io.github.dsheirer.module.decode.event.DecodeEvent;
import io.github.dsheirer.module.decode.event.DecodeEventType;
import io.github.dsheirer.module.decode.p25.P25DecodeEvent;
import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
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.MacPduType;
@@ -96,7 +97,7 @@ import org.slf4j.LoggerFactory;
public class P25P2DecoderState extends TimeslotDecoderState implements IdentifierUpdateListener
{
private final static Logger mLog = LoggerFactory.getLogger(P25P2DecoderState.class);
private static int SYSTEM_CONTROLLER = 0xFFFFFF;
private ChannelType mChannelType;
private PatchGroupManager mPatchGroupManager = new PatchGroupManager();
private P25P2NetworkConfigurationMonitor mNetworkConfigurationMonitor = new P25P2NetworkConfigurationMonitor();
@@ -216,12 +217,28 @@ public class P25P2DecoderState extends TimeslotDecoderState implements Identifie
//the closing event.
for(Identifier identifier : mac.getIdentifiers())
{
//Add to the identifier collection after filtering through the patch group manager
getIdentifierCollection().update(mPatchGroupManager.update(identifier));
if(identifier.getRole() == Role.FROM && identifier instanceof APCO25RadioIdentifier)
{
int value = ((APCO25RadioIdentifier)identifier).getValue();
if(value == SYSTEM_CONTROLLER)
{
//ignore so we don't overwrite the real from radio identifier
}
else
{
//Add to the identifier collection after filtering through the patch group manager
getIdentifierCollection().update(mPatchGroupManager.update(identifier));
}
}
else
{
//Add to the identifier collection after filtering through the patch group manager
getIdentifierCollection().update(mPatchGroupManager.update(identifier));
}
}
closeCurrentCallEvent(message.getTimestamp(), false);
getIdentifierCollection().remove(IdentifierClass.USER);
closeCurrentCallEvent(message.getTimestamp(), true);
}
break;
case TDMA_0_NULL_INFORMATION_MESSAGE:

View File

@@ -18,7 +18,11 @@
*/
package io.github.dsheirer.module.decode.p25.phase2;
import io.github.dsheirer.alias.Alias;
import io.github.dsheirer.alias.AliasList;
import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.alias.id.record.Record;
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
import io.github.dsheirer.audio.playback.AudioPlaybackManager;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.controller.channel.Channel;
@@ -26,15 +30,21 @@ 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.MessageInjectionModule;
import io.github.dsheirer.message.MessageProviderModule;
import io.github.dsheirer.message.StuffBitsMessage;
import io.github.dsheirer.module.Module;
import io.github.dsheirer.module.ProcessingChain;
import io.github.dsheirer.module.decode.DecoderFactory;
import io.github.dsheirer.module.decode.DecoderType;
import io.github.dsheirer.module.decode.p25.audio.P25P2AudioModule;
import io.github.dsheirer.module.decode.p25.phase1.P25P1MessageFramer;
import io.github.dsheirer.module.decode.p25.phase1.P25P1MessageProcessor;
import io.github.dsheirer.module.decode.p25.phase1.message.pdu.PDUSequence;
import io.github.dsheirer.module.decode.p25.phase2.enumeration.DataUnitID;
import io.github.dsheirer.module.decode.p25.phase2.enumeration.ScrambleParameters;
import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.protocol.Protocol;
import io.github.dsheirer.record.AudioRecordingManager;
import io.github.dsheirer.record.binary.BinaryReader;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.ReusableByteBuffer;
@@ -44,9 +54,14 @@ import io.github.dsheirer.source.tuner.configuration.TunerConfigurationModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.function.Consumer;
/**
* P25 Sync Detector and Message Framer. Includes capability to detect PLL out-of-phase lock errors
@@ -206,74 +221,101 @@ public class P25P2MessageFramer implements Listener<Dibit>
public static void main(String[] args)
{
Path directory = Paths.get("/home/denny/temp/Harris P25-2 Logs/bits");
// Path directory = Paths.get("/media/denny/500G1EXT4/PBITRecordings");
ScrambleParameters scrambleParameters = new ScrambleParameters(123654, 813, 10); //Hills
// ScrambleParameters scrambleParameters = new ScrambleParameters(1, 972, 972));
// ScrambleParameters scrambleParameters = new ScrambleParameters(781824, 686, 677)); //CNYICC - Rome
UserPreferences userPreferences = new UserPreferences();
AliasModel aliasModel = new AliasModel();
SourceManager sourceManager = new SourceManager(null, new SettingsManager(new TunerConfigurationModel()), userPreferences);
AudioPlaybackManager audioPlaybackManager = new AudioPlaybackManager(userPreferences);
Channel channel = new Channel("Phase 2 Test");
channel.setDecodeConfiguration(new DecodeConfigP25Phase2());
AliasList aliasList = new AliasList("Test Alias List");
Alias alias = new Alias("TG Range 1-65535");
alias.addAliasID(new Record());
alias.addAliasID(new TalkgroupRange(Protocol.APCO25, 1, 65535));
aliasList.addAlias(alias);
AudioRecordingManager recordingManager = new AudioRecordingManager(userPreferences);
recordingManager.start();
ProcessingChain processingChain = new ProcessingChain(channel, new AliasModel());
//Audio packets are routed through the audio packet manager for metadata enrichment and then
//distributed to the audio packet processors (ie playback, recording, streaming, etc.)
// AudioPacketManager audioPacketManager = new AudioPacketManager(aliasModel);
// audioPacketManager.addListener(audioPlaybackManager);
// audioPacketManager.start();
processingChain.addAudioSegmentListener(recordingManager);
processingChain.addModule(new P25P2DecoderState(channel, 0));
processingChain.addModule(new P25P2DecoderState(channel, 1));
processingChain.addModule(new P25P2AudioModule(userPreferences, 0, aliasList));
processingChain.addModule(new P25P2AudioModule(userPreferences, 1, aliasList));
MessageProviderModule messageProviderModule = new MessageProviderModule();
processingChain.addModule(messageProviderModule);
Channel channel = new Channel();
DecodeConfigP25Phase2 decodeP2 = new DecodeConfigP25Phase2();
// decodeP2.setScrambleParameters(new ScrambleParameters(1, 972, 972));
decodeP2.setScrambleParameters(new ScrambleParameters(781824, 686, 677)); //CNYICC - Rome
channel.setDecodeConfiguration(decodeP2);
List<Module> modules = DecoderFactory.getModules(null, channel, aliasModel, userPreferences);
MessageInjectionModule messageInjectionModule = new MessageInjectionModule();
modules.add(messageInjectionModule);
ProcessingChain processingChain = new ProcessingChain(channel, aliasModel);
// processingChain.addAudioPacketListener(audioPacketManager);
processingChain.addModules(modules);
processingChain.start();
P25P2MessageFramer messageFramer = new P25P2MessageFramer(null, DecoderType.P25_PHASE1.getProtocol().getBitRate());
messageFramer.setScrambleParameters(decodeP2.getScrambleParameters());
P25P2MessageProcessor messageProcessor = new P25P2MessageProcessor();
// P25P2CallSequenceRecorder frameRecorder = new P25P2CallSequenceRecorder(new UserPreferences(), 154250000);
messageFramer.setListener(messageProcessor);
messageProcessor.setMessageListener(new Listener<IMessage>()
try(OutputStream logOutput = Files.newOutputStream(directory.resolve("log.txt")))
{
@Override
public void receive(IMessage message)
try
{
// if(message.getTimeslot() == 0)
// {
mLog.debug(message.toString());
// }
DirectoryStream<Path> stream = Files.newDirectoryStream(directory, "*PHASE2_Hills*TRAFFIC.bits");
messageInjectionModule.receive(message);
// frameRecorder.receive(message);
stream.forEach(new Consumer<Path>()
{
@Override
public void accept(Path path)
{
mLog.debug("Processing:" + path.toString());
try
{
logOutput.write(("Processing:" + path.toString() + "\n").getBytes());
}
catch(IOException ioe)
{
mLog.error("Error", ioe);
}
P25P2MessageFramer messageFramer = new P25P2MessageFramer(null, DecoderType.P25_PHASE2.getProtocol().getBitRate());
messageFramer.setScrambleParameters(scrambleParameters);
P25P2MessageProcessor messageProcessor = new P25P2MessageProcessor();
messageFramer.setListener(messageProcessor);
messageProcessor.setMessageListener(new Listener<IMessage>()
{
@Override
public void receive(IMessage message)
{
messageProviderModule.receive(message);
try
{
logOutput.write(message.toString().getBytes());
logOutput.write("\n".getBytes());
}
catch(IOException ioe)
{
mLog.error("Error", ioe);
}
// mLog.debug(message.toString());
}
});
try(BinaryReader reader = new BinaryReader(path, 200))
{
while(reader.hasNext())
{
ReusableByteBuffer buffer = reader.next();
messageFramer.receive(buffer);
}
}
catch(Exception ioe)
{
ioe.printStackTrace();
}
}
}
);
}
});
// Path path = Paths.get("/media/denny/500G1EXT4/RadioRecordings/APCO25P2/DFW Airport Encrypted/20190321_192101_12000BPS_APCO25PHASE2_DFW_Irving_DFW_Phase_II_baseband_20181015_182924_good_phase_2.wav.bits");
// Path path = Paths.get("/media/denny/500G1EXT4/RadioRecordings/APCO25P2/DFW Airport Encrypted/20190224_101332_12000BPS_APCO25PHASE2_DFWAirport_Site_857_3875_baseband_20181213_223136.bits");
// Path path = Paths.get("/media/denny/500G1EXT4/RadioRecordings/APCO25P2/CNYICC/20190323_042605_12000BPS_APCO25PHASE2_CNYICC_ROME_154_250_1.bits");
// Path path = Paths.get("/media/denny/500G1EXT4/RadioRecordings/APCO25P2/CNYICC/20190323_042806_12000BPS_APCO25PHASE2_CNYICC_ROME_154_250_3.bits");
// Path path = Paths.get("/media/denny/500G1EXT4/RadioRecordings/APCO25P2/CNYICC/20190323_042830_12000BPS_APCO25PHASE2_CNYICC_ROME_154_250_4.bits");
// Path path = Paths.get("/media/denny/500G1EXT4/RadioRecordings/APCO25P2/CNYICC/20190323_042853_12000BPS_APCO25PHASE2_CNYICC_ROME_154_250_5.bits");
Path path = Paths.get("/media/denny/500G1EXT4/RadioRecordings/APCO25P2/CNYICC/20190323_042917_12000BPS_APCO25PHASE2_CNYICC_ROME_154_250_6.bits");
// Path path = Paths.get("/media/denny/500G1EXT4/RadioRecordings/APCO25P2/CNYICC/20190323_042938_12000BPS_APCO25PHASE2_CNYICC_ROME_154_250_7.bits");
try(BinaryReader reader = new BinaryReader(path, 200))
{
while(reader.hasNext())
catch(IOException ioe)
{
messageFramer.receive(reader.next());
mLog.error("Error", ioe);
}
}
catch(Exception ioe)
catch(IOException ioe)
{
ioe.printStackTrace();
mLog.error("Error", ioe);
}
// frameRecorder.stop();
}
}

View File

@@ -62,8 +62,8 @@ public class CallAlertAbbreviated extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
return sb.toString();
}

View File

@@ -66,8 +66,8 @@ public class CallAlertExtended extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceSuid());
sb.append(" TO:").append(getTargetAddress());
return sb.toString();
}

View File

@@ -73,7 +73,7 @@ public class EndPushToTalk extends MacStructure
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("FROM:").append(getSourceAddress());
sb.append("FM:").append(getSourceAddress());
sb.append(" TO:").append(getGroupAddress());
sb.append(" NAC:").append(getNAC());

View File

@@ -72,8 +72,8 @@ public class ExtendedFunctionCommandExtended extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceSuid());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FUNCTION:").append(getExtendedFunction());
sb.append(" ARGUMENTS:").append(getArguments());
return sb.toString();

View File

@@ -62,8 +62,8 @@ public class GroupAffiliationQueryAbbreviated extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
return sb.toString();
}

View File

@@ -66,8 +66,8 @@ public class GroupAffiliationQueryExtended extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceSuid());
sb.append(" TO:").append(getTargetAddress());
return sb.toString();
}

View File

@@ -72,8 +72,8 @@ public class GroupVoiceChannelGrantAbbreviated extends MacStructure implements I
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getGroupAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getGroupAddress());
sb.append(" CHAN:").append(getChannel());
sb.append(" ").append(getServiceOptions());
return sb.toString();

View File

@@ -74,8 +74,8 @@ public class GroupVoiceChannelGrantExtended extends MacStructure implements IFre
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getGroupAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getGroupAddress());
sb.append(" CHAN:").append(getChannel());
sb.append(" ").append(getServiceOptions());
return sb.toString();

View File

@@ -65,8 +65,8 @@ public class GroupVoiceChannelUserAbbreviated extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getGroupAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getGroupAddress());
sb.append(" ").append(getServiceOptions());
return sb.toString();
}

View File

@@ -73,8 +73,8 @@ public class GroupVoiceChannelUserExtended extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getGroupAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getGroupAddress());
sb.append(" SUID:").append(getSourceSuid());
sb.append(" ").append(getServiceOptions());
return sb.toString();

View File

@@ -65,8 +65,8 @@ public class GroupVoiceServiceRequest extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getGroupAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getGroupAddress());
sb.append(" ").append(getServiceOptions());
return sb.toString();
}

View File

@@ -65,8 +65,8 @@ public class MessageUpdateAbbreviated extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
sb.append(" MSG:").append(getShortDataMessage());
return sb.toString();
}

View File

@@ -69,8 +69,8 @@ public class MessageUpdateExtended extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceSuid());
sb.append(" TO:").append(getTargetAddress());
sb.append(" MSG:").append(getShortDataMessage());
return sb.toString();
}

View File

@@ -78,7 +78,7 @@ public class PushToTalk extends MacStructure
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("FROM:").append(getSourceAddress());
sb.append("FM:").append(getSourceAddress());
sb.append(" TO:").append(getGroupAddress());
if(isEncrypted())

View File

@@ -65,8 +65,8 @@ public class RadioUnitMonitorCommand extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
if(isSilentMonitor())
{

View File

@@ -70,8 +70,8 @@ public class RadioUnitMonitorCommandExtended extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceSuid());
sb.append(" TO:").append(getTargetAddress());
if(isSilentMonitor())
{

View File

@@ -62,8 +62,8 @@ public class StatusQueryAbbreviated extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
return sb.toString();
}

View File

@@ -66,8 +66,8 @@ public class StatusQueryExtended extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceSuid());
sb.append(" TO:").append(getTargetAddress());
return sb.toString();
}

View File

@@ -68,8 +68,8 @@ public class StatusUpdateAbbreviated extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
sb.append(" UNIT:").append(getUnitStatus());
sb.append(" USER:").append(getUserStatus());
return sb.toString();

View File

@@ -72,8 +72,8 @@ public class StatusUpdateExtended extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceSuid());
sb.append(" TO:").append(getTargetAddress());
sb.append(" UNIT:").append(getUnitStatus());
sb.append(" USER:").append(getUserStatus());
return sb.toString();

View File

@@ -62,8 +62,8 @@ public class UnitRegistrationCommandAbbreviated extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
return sb.toString();
}

View File

@@ -65,8 +65,8 @@ public class UnitToUnitAnswerRequestAbbreviated extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
sb.append(" ").append(getServiceOptions());
return sb.toString();
}

View File

@@ -69,8 +69,8 @@ public class UnitToUnitAnswerRequestExtended extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceSuid());
sb.append(" TO:").append(getTargetAddress());
sb.append(" ").append(getServiceOptions());
return sb.toString();
}

View File

@@ -69,8 +69,8 @@ public class UnitToUnitVoiceChannelGrantAbbreviated extends MacStructure impleme
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
sb.append(" CHAN:").append(getChannel());
return sb.toString();
}

View File

@@ -75,8 +75,8 @@ public class UnitToUnitVoiceChannelGrantExtended extends MacStructure implements
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceSuid());
sb.append(" TO:").append(getTargetAddress());
sb.append(" CHAN:").append(getChannel());
return sb.toString();
}

View File

@@ -68,8 +68,8 @@ public class UnitToUnitVoiceChannelGrantUpdateAbbreviated extends MacStructure i
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
sb.append(" CHAN:").append(getChannel());
return sb.toString();
}

View File

@@ -76,8 +76,8 @@ public class UnitToUnitVoiceChannelGrantUpdateExtended extends MacStructure impl
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceSuid());
sb.append(" TO:").append(getTargetAddress());
sb.append(" CHAN:").append(getChannel());
return sb.toString();
}

View File

@@ -65,8 +65,8 @@ public class UnitToUnitVoiceChannelUserAbbreviated extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
sb.append(" ").append(getServiceOptions());
return sb.toString();
}

View File

@@ -72,8 +72,8 @@ public class UnitToUnitVoiceChannelUserExtended extends MacStructure
{
StringBuilder sb = new StringBuilder();
sb.append(getOpcode());
sb.append(" TO:").append(getTargetAddress());
sb.append(" FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
sb.append(" SUID:").append(getSourceSuid());
sb.append(" ").append(getServiceOptions());
return sb.toString();