mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Initial commit of redesigned internal processing and audio management.
Note: Several of the decoders are currently non-functioning in this commit. If you want the latest functioning codebase, please checkout the commit prior to this one. All decoders will eventually be updated with this new architecture. Currently broken: - Logging and recording - Aux decoders (Fleetsync/MDC/LoJack/Tait) - LTR/Passport decoders Changes in this commit: - Module architecture for decoders and components with central provisioning by the DecoderFactory - Transition from Complex sample stream processing to float buffer processing for improved memory management - Redesigned filter structures - to support buffers and streams - Resolved several memory leak issues - Universal sharing of the thread pool manager - Added centralized audio management with call/user prioritization and new gui with mute/volume controls - Embedded audio metadata for eventual streaming support - Redesigned ProcessingChain to support independent re-use - Added new TrafficChannelManager to handle traffic channel allocations - Traffic Channel pool size and Call timeout available in P25 and MPT1327 configs - Redesigned channel and decoder gui components
This commit is contained in:
45
src/module/decode/ltrnet/DecodeConfigLTRNet.java
Normal file
45
src/module/decode/ltrnet/DecodeConfigLTRNet.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 module.decode.ltrnet;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
||||
import message.MessageDirection;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
|
||||
public class DecodeConfigLTRNet extends DecodeConfiguration
|
||||
{
|
||||
private MessageDirection mMessageDirection = MessageDirection.OSW;
|
||||
|
||||
public DecodeConfigLTRNet()
|
||||
{
|
||||
super( DecoderType.LTR_NET );
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "direction" )
|
||||
public MessageDirection getMessageDirection()
|
||||
{
|
||||
return mMessageDirection;
|
||||
}
|
||||
|
||||
public void setMessageDirection( MessageDirection direction )
|
||||
{
|
||||
mMessageDirection = direction;
|
||||
}
|
||||
}
|
||||
238
src/module/decode/ltrnet/LTRCallEvent.java
Normal file
238
src/module/decode/ltrnet/LTRCallEvent.java
Normal file
@@ -0,0 +1,238 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 module.decode.ltrnet;
|
||||
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.ltrstandard.LTRStandardMessage;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
|
||||
public class LTRCallEvent extends CallEvent
|
||||
{
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
private int mValidCallMessages = 1;
|
||||
|
||||
public LTRCallEvent( CallEventType callEventType,
|
||||
AliasList aliasList,
|
||||
String fromID,
|
||||
String toID,
|
||||
String channel,
|
||||
long frequency,
|
||||
String details )
|
||||
{
|
||||
super( DecoderType.LTR_STANDARD, callEventType,
|
||||
aliasList, fromID, toID, details );
|
||||
|
||||
mChannel = channel;
|
||||
mFrequency = frequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* LTR sends multiple CALL messages during a call. In order to detect noise
|
||||
* bursts from valid calls, send every valid call message to this method
|
||||
* and the event will keep a tally of valid call messages in order to
|
||||
* determine if the call was a valid (and loggable) call event.
|
||||
*/
|
||||
public boolean addMessage( LTRStandardMessage message )
|
||||
{
|
||||
String talkgroup = message.getTalkgroupID();
|
||||
|
||||
if( talkgroup.contentEquals( getToID() ) )
|
||||
{
|
||||
mValidCallMessages++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the message's talkgroup matches this call event. Counts the
|
||||
* number of messages that match this call event to use in determining if
|
||||
* a call event is valid or an isolated (errant) message.
|
||||
*
|
||||
* See: isValid()
|
||||
*/
|
||||
public boolean isMatchingTalkgroup( LTRNetMessage message )
|
||||
{
|
||||
String talkgroup = message.getTalkgroupID();
|
||||
|
||||
if( talkgroup != null && getToID() != null &&
|
||||
talkgroup.contentEquals( getToID() ) )
|
||||
{
|
||||
mValidCallMessages++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
if( getCallEventType() == CallEventType.CALL )
|
||||
{
|
||||
return mValidCallMessages > 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Alias getAlias( String talkgroup )
|
||||
{
|
||||
if( hasAliasList() )
|
||||
{
|
||||
return getAliasList().getTalkgroupAlias( talkgroup );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
if( mCallEventType == CallEventType.CALL ||
|
||||
mCallEventType == CallEventType.REGISTER ||
|
||||
mCallEventType == CallEventType.ID_UNIQUE )
|
||||
{
|
||||
if( hasAliasList() )
|
||||
{
|
||||
try
|
||||
{
|
||||
int radioID = Integer.parseInt( getFromID() );
|
||||
|
||||
return mAliasList.getUniqueID( radioID );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
//Do nothing, we couldn't parse the int radio id value
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( mCallEventType == CallEventType.REGISTER_ESN )
|
||||
{
|
||||
if( hasAliasList() )
|
||||
{
|
||||
return mAliasList.getESNAlias( getFromID() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return getAlias( getFromID() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
return getAlias( getToID() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getChannel()
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrequency()
|
||||
{
|
||||
return mFrequency;
|
||||
}
|
||||
|
||||
public static class Builder
|
||||
{
|
||||
/* Required parameters */
|
||||
private CallEventType mCallEventType;
|
||||
|
||||
/* Optional parameters */
|
||||
private AliasList mAliasList;
|
||||
private String mFromID;
|
||||
private String mToID;
|
||||
private String mDetails;
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
|
||||
public Builder( CallEventType callEventType )
|
||||
{
|
||||
mCallEventType = callEventType;
|
||||
}
|
||||
|
||||
public Builder aliasList( AliasList aliasList )
|
||||
{
|
||||
mAliasList = aliasList;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder from( String val )
|
||||
{
|
||||
mFromID = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder channel( String channel )
|
||||
{
|
||||
mChannel = channel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder details( String details )
|
||||
{
|
||||
mDetails = details;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder frequency( long frequency )
|
||||
{
|
||||
mFrequency = frequency;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder to( String toID )
|
||||
{
|
||||
mToID = toID;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LTRCallEvent build()
|
||||
{
|
||||
return new LTRCallEvent( this );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor for the builder
|
||||
*/
|
||||
private LTRCallEvent( Builder builder )
|
||||
{
|
||||
this( builder.mCallEventType,
|
||||
builder.mAliasList,
|
||||
builder.mFromID,
|
||||
builder.mToID,
|
||||
builder.mChannel,
|
||||
builder.mFrequency,
|
||||
builder.mDetails );
|
||||
}
|
||||
|
||||
}
|
||||
113
src/module/decode/ltrnet/LTRNetDecoder.java
Normal file
113
src/module/decode/ltrnet/LTRNetDecoder.java
Normal file
@@ -0,0 +1,113 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 module.decode.ltrnet;
|
||||
|
||||
import instrument.Instrumentable;
|
||||
import instrument.tap.Tap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import message.MessageDirection;
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import alias.AliasList;
|
||||
import bits.MessageFramer;
|
||||
import bits.SyncPattern;
|
||||
import dsp.fsk.LTRFSKDecoder;
|
||||
|
||||
public class LTRNetDecoder extends Decoder
|
||||
implements IRealBufferListener, Instrumentable
|
||||
{
|
||||
public static final int LTR_STANDARD_MESSAGE_LENGTH = 40;
|
||||
private LTRFSKDecoder mLTRFSKDecoder;
|
||||
private MessageFramer mLTRMessageFramer;
|
||||
private LTRNetMessageProcessor mLTRMessageProcessor;
|
||||
|
||||
private List<Tap> mAvailableTaps;
|
||||
|
||||
public LTRNetDecoder( DecodeConfigLTRNet config, AliasList aliasList )
|
||||
{
|
||||
super( new LTRNetDecoderState( aliasList ) );
|
||||
|
||||
mLTRFSKDecoder = new LTRFSKDecoder();
|
||||
|
||||
|
||||
if( config.getMessageDirection() == MessageDirection.OSW )
|
||||
{
|
||||
mLTRMessageFramer =
|
||||
new MessageFramer( SyncPattern.LTR_STANDARD_OSW.getPattern(),
|
||||
LTR_STANDARD_MESSAGE_LENGTH );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLTRMessageFramer =
|
||||
new MessageFramer( SyncPattern.LTR_STANDARD_ISW.getPattern(),
|
||||
LTR_STANDARD_MESSAGE_LENGTH );
|
||||
}
|
||||
|
||||
mLTRFSKDecoder.addListener( mLTRMessageFramer );
|
||||
|
||||
mLTRMessageProcessor = new LTRNetMessageProcessor(
|
||||
config.getMessageDirection(), aliasList );
|
||||
|
||||
mLTRMessageFramer.addMessageListener( mLTRMessageProcessor );
|
||||
|
||||
mLTRMessageProcessor.setMessageListener( mMessageBroadcaster );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.LTR_NET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
{
|
||||
return mLTRFSKDecoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tap> getTaps()
|
||||
{
|
||||
if( mAvailableTaps == null )
|
||||
{
|
||||
mAvailableTaps = new ArrayList<Tap>();
|
||||
|
||||
mAvailableTaps.addAll( mLTRFSKDecoder.getTaps() );
|
||||
}
|
||||
|
||||
return mAvailableTaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTap( Tap tap )
|
||||
{
|
||||
mLTRFSKDecoder.addTap( tap );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTap( Tap tap )
|
||||
{
|
||||
mLTRFSKDecoder.removeTap( tap );
|
||||
}
|
||||
}
|
||||
166
src/module/decode/ltrnet/LTRNetDecoderPanel.java
Normal file
166
src/module/decode/ltrnet/LTRNetDecoderPanel.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 module.decode.ltrnet;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import module.decode.state.ChangedAttribute;
|
||||
import module.decode.state.DecoderPanel;
|
||||
import settings.ColorSetting;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
import alias.Alias;
|
||||
|
||||
public class LTRNetDecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocol = new JLabel( "LTR-Net" );
|
||||
private JLabel mTalkgroup = new JLabel();
|
||||
private JLabel mTalkgroupAlias = new JLabel();
|
||||
|
||||
private JLabel mLCN = new JLabel( "LCN:" );
|
||||
private JLabel mDescription = new JLabel();
|
||||
|
||||
public LTRNetDecoderPanel( SettingsManager settingsManager, LTRNetDecoder decoder )
|
||||
{
|
||||
super( settingsManager, decoder );
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
super.init();
|
||||
|
||||
setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[]0[]0[]") );
|
||||
|
||||
mProtocol.setFont( mFontDecoder );
|
||||
mProtocol.setForeground( mColorLabelDecoder );
|
||||
|
||||
mTalkgroup.setFont( mFontDecoder );
|
||||
mTalkgroup.setForeground( mColorLabelDecoder );
|
||||
|
||||
mTalkgroupAlias.setFont( mFontDecoder );
|
||||
mTalkgroupAlias.setForeground( mColorLabelDecoder );
|
||||
|
||||
mLCN.setFont( mFontDecoder );
|
||||
mLCN.setForeground( mColorLabelDecoder );
|
||||
|
||||
mDescription.setFont( mFontDecoder );
|
||||
mDescription.setForeground( mColorLabelDecoder );
|
||||
|
||||
add( mProtocol );
|
||||
add( mTalkgroup );
|
||||
add( mTalkgroupAlias, "wrap" );
|
||||
|
||||
add( mLCN );
|
||||
add( mDescription, "span,wrap" );
|
||||
}
|
||||
|
||||
private LTRNetDecoderState getDecoderState()
|
||||
{
|
||||
return (LTRNetDecoderState)getDecoder().getDecoderState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( final ChangedAttribute changedAttribute )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
LTRNetDecoderState state = getDecoderState();
|
||||
|
||||
switch( changedAttribute )
|
||||
{
|
||||
case TO_TALKGROUP:
|
||||
mTalkgroup.setText( state.getToTalkgroup() );
|
||||
break;
|
||||
case TO_TALKGROUP_ALIAS:
|
||||
Alias tgAlias = state.getToTalkgroupAlias();
|
||||
|
||||
if( tgAlias != null )
|
||||
{
|
||||
mTalkgroupAlias.setText( tgAlias.getName() );
|
||||
String iconNameString = tgAlias.getIconName();
|
||||
mTalkgroupAlias.setIcon( mSettingsManager
|
||||
.getImageIcon( iconNameString, 12 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mTalkgroupAlias.setText( null );
|
||||
mTalkgroupAlias.setIcon( null );
|
||||
}
|
||||
break;
|
||||
case DESCRIPTION:
|
||||
mDescription.setText( state.getDescription() );
|
||||
break;
|
||||
case CHANNEL_NUMBER:
|
||||
mLCN.setText( "LCN: " + state.getChannelNumber() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged( Setting setting )
|
||||
{
|
||||
super.settingChanged( setting );
|
||||
|
||||
if( setting instanceof ColorSetting )
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting)setting;
|
||||
|
||||
switch( colorSetting.getColorSettingName() )
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
if( mProtocol != null )
|
||||
{
|
||||
mProtocol.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
if( mTalkgroup != null )
|
||||
{
|
||||
mTalkgroup.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
if( mTalkgroupAlias != null )
|
||||
{
|
||||
mTalkgroupAlias.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
if( mLCN != null )
|
||||
{
|
||||
mLCN.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
if( mDescription != null )
|
||||
{
|
||||
mDescription.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
707
src/module/decode/ltrnet/LTRNetDecoderState.java
Normal file
707
src/module/decode/ltrnet/LTRNetDecoderState.java
Normal file
@@ -0,0 +1,707 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 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 module.decode.ltrnet;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.event.CallEvent.CallEventType;
|
||||
import module.decode.state.ChangedAttribute;
|
||||
import module.decode.state.DecoderState;
|
||||
import module.decode.state.DecoderStateEvent;
|
||||
import module.decode.state.DecoderStateEvent.Event;
|
||||
import module.decode.state.State;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
|
||||
public class LTRNetDecoderState extends DecoderState
|
||||
{
|
||||
private DecimalFormat mDecimalFormatter = new DecimalFormat( "0.00000" );
|
||||
|
||||
private TreeSet<String> mTalkgroups = new TreeSet<String>();
|
||||
private TreeSet<String> mTalkgroupsFirstHeard = new TreeSet<String>();
|
||||
private TreeSet<String> mESNs = new TreeSet<String>();
|
||||
private TreeSet<Integer> mUniqueIDs = new TreeSet<Integer>();
|
||||
private TreeSet<String> mNeighborIDs = new TreeSet<String>();
|
||||
private TreeSet<String> mSiteIDs = new TreeSet<String>();
|
||||
private HashMap<Integer,Long> mReceiveFrequencies =
|
||||
new HashMap<Integer,Long>();
|
||||
private HashMap<Integer,Long> mTransmitFrequencies =
|
||||
new HashMap<Integer,Long>();
|
||||
private HashMap<Integer,String> mActiveCalls = new HashMap<Integer,String>();
|
||||
|
||||
private String mTalkgroup;
|
||||
private Alias mTalkgroupAlias;
|
||||
private String mDescription;
|
||||
private int mChannelNumber;
|
||||
private long mFrequency = 0;
|
||||
|
||||
public LTRNetDecoderState( AliasList aliasList )
|
||||
{
|
||||
super( aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
{
|
||||
if( message.isValid() )
|
||||
{
|
||||
if( message instanceof LTRNetOSWMessage )
|
||||
{
|
||||
LTRNetOSWMessage ltr = (LTRNetOSWMessage)message;
|
||||
|
||||
switch( ltr.getMessageType() )
|
||||
{
|
||||
case CA_STRT:
|
||||
case CA_ENDD:
|
||||
if( mChannelNumber == 0 )
|
||||
{
|
||||
mChannelNumber = ltr.getChannel();
|
||||
broadcast( ChangedAttribute.CHANNEL_NUMBER );
|
||||
}
|
||||
|
||||
if( ltr.getChannel() == 31 )
|
||||
{
|
||||
processCallEndMessage( ltr );
|
||||
}
|
||||
else if( ltr.getChannel() == mChannelNumber )
|
||||
{
|
||||
processCallMessage( ltr );
|
||||
}
|
||||
else
|
||||
{
|
||||
processCallDetectMessage( ltr );
|
||||
}
|
||||
break;
|
||||
case SY_IDLE:
|
||||
if( mChannelNumber != ltr.getChannel() )
|
||||
{
|
||||
mChannelNumber = ltr.getChannel();
|
||||
broadcast( ChangedAttribute.CHANNEL_NUMBER );
|
||||
}
|
||||
break;
|
||||
case MA_CHNH:
|
||||
break;
|
||||
case MA_CHNL:
|
||||
break;
|
||||
case FQ_RXHI:
|
||||
case FQ_RXLO:
|
||||
if( ltr.getFrequency() > 0 )
|
||||
{
|
||||
mReceiveFrequencies.put( ltr.getHomeRepeater(),
|
||||
ltr.getFrequency() );
|
||||
}
|
||||
break;
|
||||
case FQ_TXHI:
|
||||
case FQ_TXLO:
|
||||
if( ltr.getFrequency() > 0 )
|
||||
{
|
||||
mTransmitFrequencies.put( ltr.getHomeRepeater(),
|
||||
ltr.getFrequency() );
|
||||
}
|
||||
break;
|
||||
case ID_NBOR:
|
||||
String neighborID = ltr.getNeighborID();
|
||||
|
||||
if( neighborID != null )
|
||||
{
|
||||
mNeighborIDs.add( neighborID );
|
||||
}
|
||||
break;
|
||||
case ID_UNIQ:
|
||||
int uniqueID = ltr.getRadioUniqueID();
|
||||
|
||||
if( uniqueID != LTRNetOSWMessage.INT_NULL_VALUE )
|
||||
{
|
||||
mUniqueIDs.add( uniqueID );
|
||||
}
|
||||
|
||||
if( getCurrentLTRCallEvent() == null )
|
||||
{
|
||||
mCurrentCallEvent = new LTRCallEvent.Builder( CallEventType.REGISTER )
|
||||
.aliasList( getAliasList() )
|
||||
.channel( String.valueOf( mChannelNumber ) )
|
||||
.frequency( mFrequency )
|
||||
.from( String.valueOf( uniqueID ) )
|
||||
.build();
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentCallEvent.setFromID(
|
||||
String.valueOf( ltr.getRadioUniqueID() ) );
|
||||
mCurrentCallEvent.setDetails( "Unique ID" );
|
||||
|
||||
broadcast( mCurrentCallEvent );
|
||||
}
|
||||
|
||||
mTalkgroup = String.valueOf( uniqueID );
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP );
|
||||
|
||||
mTalkgroupAlias = ltr.getRadioUniqueIDAlias();
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS );
|
||||
break;
|
||||
case ID_SITE:
|
||||
String siteID = ltr.getSiteID();
|
||||
|
||||
if( siteID != null )
|
||||
{
|
||||
mSiteIDs.add( siteID );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( message instanceof LTRNetISWMessage )
|
||||
{
|
||||
LTRNetISWMessage ltr = ((LTRNetISWMessage)message);
|
||||
|
||||
switch( ltr.getMessageType() )
|
||||
{
|
||||
case CA_STRT:
|
||||
processCallMessage( ltr );
|
||||
break;
|
||||
case CA_ENDD:
|
||||
processCallEndMessage( ltr );
|
||||
break;
|
||||
case ID_ESNH:
|
||||
case ID_ESNL:
|
||||
String esn = ltr.getESN();
|
||||
|
||||
if( !esn.contains( "xxxx" ) )
|
||||
{
|
||||
mESNs.add( ltr.getESN() );
|
||||
}
|
||||
|
||||
mDescription = "ESN";
|
||||
broadcast( ChangedAttribute.DESCRIPTION );
|
||||
|
||||
mTalkgroup = ltr.getESN();
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP );
|
||||
|
||||
mTalkgroupAlias = ltr.getESNAlias();
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS );
|
||||
|
||||
broadcast( new DecoderStateEvent( this, Event.DECODE, State.DATA ) );
|
||||
|
||||
if( mCurrentCallEvent == null )
|
||||
{
|
||||
mCurrentCallEvent = new LTRCallEvent.Builder( CallEventType.REGISTER_ESN )
|
||||
.aliasList( getAliasList() )
|
||||
.details( "ESN:" + ltr.getESN() )
|
||||
.frequency( mFrequency )
|
||||
.from( ltr.getESN() )
|
||||
.build();
|
||||
|
||||
broadcast( mCurrentCallEvent );
|
||||
}
|
||||
|
||||
break;
|
||||
case ID_UNIQ:
|
||||
int uniqueid = ltr.getRadioUniqueID();
|
||||
|
||||
if( uniqueid != LTRNetISWMessage.INT_NULL_VALUE )
|
||||
{
|
||||
mUniqueIDs.add( uniqueid );
|
||||
|
||||
mDescription = "REGISTER UID";
|
||||
broadcast( ChangedAttribute.DESCRIPTION );
|
||||
|
||||
mTalkgroup = String.valueOf( uniqueid );
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP );
|
||||
|
||||
mTalkgroupAlias = ltr.getRadioUniqueIDAlias();
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS );
|
||||
|
||||
if( getCurrentLTRCallEvent() == null )
|
||||
{
|
||||
mCurrentCallEvent = new LTRCallEvent.Builder( CallEventType.REGISTER )
|
||||
.aliasList( getAliasList() )
|
||||
.channel( String.valueOf( mChannelNumber ) )
|
||||
.frequency( mFrequency )
|
||||
.from( String.valueOf( uniqueid ) )
|
||||
.build();
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentCallEvent.setFromID(
|
||||
String.valueOf( ltr.getRadioUniqueID() ) );
|
||||
mCurrentCallEvent.setDetails( "Unique ID" );
|
||||
|
||||
broadcast( mCurrentCallEvent );
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LTRCallEvent getCurrentLTRCallEvent()
|
||||
{
|
||||
if( mCurrentCallEvent != null )
|
||||
{
|
||||
return (LTRCallEvent)mCurrentCallEvent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActivitySummary()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "Activity Summary\n" );
|
||||
sb.append( "Decoder:\tLTR-Net\n\n" );
|
||||
|
||||
if( mSiteIDs.isEmpty() )
|
||||
{
|
||||
sb.append( "Site:\tUnknown\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator<String> it = mSiteIDs.iterator();
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
sb.append( "Site:\t" );
|
||||
|
||||
String siteID = it.next();
|
||||
|
||||
sb.append( siteID );
|
||||
|
||||
if( hasAliasList() )
|
||||
{
|
||||
Alias siteAlias = getAliasList().getSiteID( String.valueOf( siteID ) );
|
||||
|
||||
if( siteAlias != null )
|
||||
{
|
||||
sb.append( " " );
|
||||
sb.append( siteAlias.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\nLCNs (transmit | receive)\n" );
|
||||
|
||||
if( mReceiveFrequencies.isEmpty() && mTransmitFrequencies.isEmpty() )
|
||||
{
|
||||
sb.append( " None\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int x = 1; x < 21; x++ )
|
||||
{
|
||||
long rcv = 0;
|
||||
|
||||
if( mReceiveFrequencies.containsKey( x ) )
|
||||
{
|
||||
rcv = mReceiveFrequencies.get( x );
|
||||
}
|
||||
|
||||
long xmt = 0;
|
||||
|
||||
if( mTransmitFrequencies.containsKey( x ) )
|
||||
{
|
||||
xmt = mTransmitFrequencies.get( x );
|
||||
}
|
||||
|
||||
if( rcv > 0 || xmt > 0 )
|
||||
{
|
||||
if( x < 10 )
|
||||
{
|
||||
sb.append( " " );
|
||||
}
|
||||
|
||||
sb.append( x );
|
||||
sb.append( ": " );
|
||||
|
||||
if( xmt == 0 )
|
||||
{
|
||||
sb.append( "---.-----" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( mDecimalFormatter.format( (double)xmt/1E6d ) );
|
||||
}
|
||||
sb.append( " | " );
|
||||
|
||||
if( rcv == 0 )
|
||||
{
|
||||
sb.append( "---.-----" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( mDecimalFormatter.format( (double)rcv/1E6d ) );
|
||||
}
|
||||
|
||||
if( x == mChannelNumber )
|
||||
{
|
||||
sb.append( " **" );
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\nTalkgroups\n" );
|
||||
|
||||
if( mTalkgroups.isEmpty() )
|
||||
{
|
||||
sb.append( " None\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator<String> it = mTalkgroups.iterator();
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
String tgid = it.next();
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( tgid );
|
||||
sb.append( " " );
|
||||
|
||||
if( hasAliasList() )
|
||||
{
|
||||
Alias alias = getAliasList().getTalkgroupAlias( tgid );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( alias.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\nRadio Unique IDs\n" );
|
||||
|
||||
if( mUniqueIDs.isEmpty() )
|
||||
{
|
||||
sb.append( " None\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator<Integer> it = mUniqueIDs.iterator();
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
int uid = it.next();
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( uid );
|
||||
sb.append( " " );
|
||||
|
||||
if( hasAliasList() )
|
||||
{
|
||||
Alias alias = getAliasList().getUniqueID( uid );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( alias.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\nESNs\n" );
|
||||
|
||||
if( mESNs.isEmpty() )
|
||||
{
|
||||
sb.append( " None\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator<String> it = mESNs.iterator();
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
String esn = it.next();
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( esn );
|
||||
sb.append( " " );
|
||||
|
||||
if( hasAliasList() )
|
||||
{
|
||||
Alias alias = getAliasList().getESNAlias( esn );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( alias.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\nNeighbor Sites\n" );
|
||||
|
||||
if( mNeighborIDs.isEmpty() )
|
||||
{
|
||||
sb.append( " None\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator<String> it = mNeighborIDs.iterator();
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
String neighbor = it.next();
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( neighbor );
|
||||
sb.append( " " );
|
||||
|
||||
if( hasAliasList() )
|
||||
{
|
||||
Alias alias = getAliasList().getSiteID( String.valueOf( neighbor ) );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( alias.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call Detect - current channel messages indicate a call on another channel
|
||||
*/
|
||||
private void processCallDetectMessage( LTRNetMessage message )
|
||||
{
|
||||
if( !mActiveCalls.containsKey( message.getChannel() ) ||
|
||||
!mActiveCalls.get( message.getChannel() ).contentEquals( message.getTalkgroupID() ) )
|
||||
{
|
||||
mActiveCalls.put( message.getChannel(), message.getTalkgroupID() );
|
||||
|
||||
int channel = message.getChannel();
|
||||
|
||||
long frequency = 0;
|
||||
|
||||
if( mTransmitFrequencies.containsKey( channel ) )
|
||||
{
|
||||
frequency = mTransmitFrequencies.get( channel );
|
||||
}
|
||||
|
||||
broadcast( new LTRCallEvent.Builder( CallEventType.CALL_DETECT )
|
||||
.aliasList( getAliasList() )
|
||||
.channel( String.valueOf( message.getChannel() ) )
|
||||
.frequency( frequency )
|
||||
.to( message.getTalkgroupID() )
|
||||
.build() );
|
||||
}
|
||||
}
|
||||
|
||||
private void processCallMessage( LTRNetMessage message )
|
||||
{
|
||||
LTRCallEvent current = getCurrentLTRCallEvent();
|
||||
|
||||
int group = message.getGroup();
|
||||
|
||||
/* If this is a new call or the talkgroup is different from the current
|
||||
* call, create a new call event */
|
||||
if( current == null || !current.isMatchingTalkgroup( message ) )
|
||||
{
|
||||
/* Invalidate the current call */
|
||||
if( current != null )
|
||||
{
|
||||
current.setValid( false );
|
||||
broadcast( current );
|
||||
}
|
||||
|
||||
mTalkgroup = message.getTalkgroupID();
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP );
|
||||
|
||||
/* A talkgroup must be seen at least once before it will be added
|
||||
* to the mTalkgroups list that is used in the activity summary,
|
||||
* so that we don't pollute the summary with one-off error talkgroups */
|
||||
if( mTalkgroupsFirstHeard.contains( mTalkgroup ) )
|
||||
{
|
||||
mTalkgroups.add( mTalkgroup );
|
||||
}
|
||||
else
|
||||
{
|
||||
mTalkgroupsFirstHeard.add( mTalkgroup );
|
||||
}
|
||||
|
||||
mTalkgroupAlias = message.getTalkgroupIDAlias();
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS );
|
||||
|
||||
CallEventType type = CallEventType.CALL;
|
||||
|
||||
if( group == 253 )
|
||||
{
|
||||
type = CallEventType.REGISTER;
|
||||
|
||||
mDescription = "REGISTER";
|
||||
broadcast( ChangedAttribute.DESCRIPTION );
|
||||
}
|
||||
else if( group == 254 )
|
||||
{
|
||||
type = CallEventType.STATION_ID;
|
||||
|
||||
mDescription = "STATION ID";
|
||||
broadcast( ChangedAttribute.DESCRIPTION );
|
||||
}
|
||||
|
||||
mCurrentCallEvent = new LTRCallEvent.Builder( type )
|
||||
.aliasList( getAliasList() )
|
||||
.channel( String.valueOf( message.getChannel() ) )
|
||||
.frequency( mFrequency )
|
||||
.to( message.getTalkgroupID() )
|
||||
.build();
|
||||
|
||||
broadcast( mCurrentCallEvent );
|
||||
|
||||
broadcast( new DecoderStateEvent( this, Event.START,
|
||||
( type == CallEventType.CALL ) ? State.CALL : State.DATA ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcast( new DecoderStateEvent( this, Event.CONTINUATION,
|
||||
( group == 253 || group == 254 ) ? State.DATA : State.CALL ) );
|
||||
}
|
||||
}
|
||||
|
||||
private void processCallEndMessage( LTRNetMessage message )
|
||||
{
|
||||
if( mCurrentCallEvent != null &&
|
||||
mCurrentCallEvent.getCallEventType() == CallEventType.CALL )
|
||||
{
|
||||
mCurrentCallEvent.setEnd( System.currentTimeMillis() );
|
||||
broadcast( mCurrentCallEvent );
|
||||
|
||||
}
|
||||
|
||||
mCurrentCallEvent = null;
|
||||
|
||||
broadcast( new DecoderStateEvent( this, Event.END, State.FADE ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the decoder state for re-use on another channel
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
mChannelNumber = 0;
|
||||
|
||||
mActiveCalls.clear();
|
||||
mESNs.clear();
|
||||
mNeighborIDs.clear();
|
||||
mReceiveFrequencies.clear();
|
||||
mSiteIDs.clear();
|
||||
mTalkgroups.clear();
|
||||
mTransmitFrequencies.clear();
|
||||
mUniqueIDs.clear();
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the decoder state after a call event
|
||||
*/
|
||||
private void resetState()
|
||||
{
|
||||
if( mCurrentCallEvent != null && mCurrentCallEvent
|
||||
.getCallEventType() == CallEventType.CALL )
|
||||
{
|
||||
mCurrentCallEvent.setEnd( System.currentTimeMillis() );
|
||||
broadcast( mCurrentCallEvent );
|
||||
}
|
||||
|
||||
mCurrentCallEvent = null;
|
||||
|
||||
mTalkgroup = null;
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP );
|
||||
|
||||
mTalkgroupAlias = null;
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS );
|
||||
|
||||
mDescription = null;
|
||||
broadcast( ChangedAttribute.DESCRIPTION );
|
||||
}
|
||||
|
||||
public String getToTalkgroup()
|
||||
{
|
||||
return mTalkgroup;
|
||||
}
|
||||
|
||||
public Alias getToTalkgroupAlias()
|
||||
{
|
||||
return mTalkgroupAlias;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
public boolean hasChannelNumber()
|
||||
{
|
||||
return mChannelNumber != 0;
|
||||
}
|
||||
|
||||
public int getChannelNumber()
|
||||
{
|
||||
return mChannelNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
/* No initialization steps required */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveDecoderStateEvent( DecoderStateEvent event )
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case RESET:
|
||||
resetState();
|
||||
break;
|
||||
case SOURCE_FREQUENCY:
|
||||
mFrequency = event.getFrequency();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
72
src/module/decode/ltrnet/LTRNetEditor.java
Normal file
72
src/module/decode/ltrnet/LTRNetEditor.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 module.decode.ltrnet;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import message.MessageDirection;
|
||||
import module.decode.DecodeEditor;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
|
||||
public class LTRNetEditor extends DecodeEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<MessageDirection> mComboDirection;
|
||||
|
||||
public LTRNetEditor( DecodeConfiguration config )
|
||||
{
|
||||
super( config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
mComboDirection = new JComboBox<MessageDirection>();
|
||||
|
||||
mComboDirection.setModel(
|
||||
new DefaultComboBoxModel<MessageDirection>( MessageDirection.values() ) );
|
||||
|
||||
mComboDirection.setSelectedItem( ((DecodeConfigLTRNet)mConfig).getMessageDirection() );
|
||||
|
||||
mComboDirection.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
MessageDirection selected = mComboDirection
|
||||
.getItemAt( mComboDirection.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
((DecodeConfigLTRNet)mConfig).setMessageDirection( selected );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Format:" ) );
|
||||
add( mComboDirection, "wrap" );
|
||||
}
|
||||
}
|
||||
345
src/module/decode/ltrnet/LTRNetISWMessage.java
Normal file
345
src/module/decode/ltrnet/LTRNetISWMessage.java
Normal file
@@ -0,0 +1,345 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 module.decode.ltrnet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import map.Plottable;
|
||||
import message.MessageDirection;
|
||||
import message.MessageType;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
import edac.CRCLTR;
|
||||
|
||||
public class LTRNetISWMessage extends LTRNetMessage
|
||||
{
|
||||
private static final int sCHIU_UNIQUE_ID = 24;
|
||||
private static final int sCHIU_ESN_LOW = 27;
|
||||
private static final int sCHIU_ESN_HIGH = 29;
|
||||
|
||||
private static final int sFREE_CALL = 21;
|
||||
private static final int sFREE_END_CALL = 23;
|
||||
private static final int sFREE_REQUEST_ACCESS = 31;
|
||||
|
||||
|
||||
private LTRNetISWMessage mAuxMessage;
|
||||
|
||||
public LTRNetISWMessage( BinaryMessage message, AliasList list )
|
||||
{
|
||||
super( message, MessageDirection.ISW, list );
|
||||
|
||||
/**
|
||||
* If the CRC fails, test for a transmitted CRC of 127 and then check
|
||||
* the Free field for special messages
|
||||
*/
|
||||
if( mCRC == CRC.FAILED_CRC && CRCLTR.getTransmittedChecksum( mMessage ) == 127 )
|
||||
{
|
||||
if( getFree() == sFREE_REQUEST_ACCESS ||
|
||||
getFree() == sFREE_END_CALL )
|
||||
{
|
||||
mCRC = CRC.PASSED;
|
||||
}
|
||||
}
|
||||
|
||||
mMessageType = getMessageType();
|
||||
}
|
||||
|
||||
public void setAuxiliaryMessage( LTRNetISWMessage message )
|
||||
{
|
||||
if( message != null )
|
||||
{
|
||||
mAuxMessage = message;
|
||||
}
|
||||
}
|
||||
|
||||
public String getESN()
|
||||
{
|
||||
if( mMessageType == MessageType.ID_ESNH )
|
||||
{
|
||||
if( mAuxMessage != null &&
|
||||
mAuxMessage.getMessageType() == MessageType.ID_ESNL )
|
||||
{
|
||||
return getESNHigh() + mAuxMessage.getESNLow();
|
||||
}
|
||||
else
|
||||
{
|
||||
return getESNHigh() + "xxxx";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mAuxMessage != null &&
|
||||
mAuxMessage.getMessageType() == MessageType.ID_ESNH )
|
||||
{
|
||||
return mAuxMessage.getESNHigh() + getESNLow();
|
||||
}
|
||||
else
|
||||
{
|
||||
return "xxxx" + getESNLow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Alias getESNAlias()
|
||||
{
|
||||
if( mAliasList != null )
|
||||
{
|
||||
return mAliasList.getESNAlias( getESN() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getESNHigh()
|
||||
{
|
||||
int esnHigh = getInt( sSIXTEEN_BITS );
|
||||
|
||||
return String.format("%04X", esnHigh & 0xFFFF );
|
||||
}
|
||||
|
||||
public String getESNLow()
|
||||
{
|
||||
int esnLow = getInt( sSIXTEEN_BITS );
|
||||
|
||||
return String.format("%04X", esnLow & 0xFFFF );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( mDatestampFormatter.format( new Date( System.currentTimeMillis() ) ) );
|
||||
sb.append( " LTRNet ISW [" );
|
||||
sb.append( mCRC.getAbbreviation() );
|
||||
sb.append( "] " );
|
||||
sb.append( getMessage() );
|
||||
pad( sb, 100 );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
switch( mMessageType )
|
||||
{
|
||||
case CA_STRT:
|
||||
sb.append( "CALL LCN:" );
|
||||
sb.append( format( getChannel(), 2 ) );
|
||||
sb.append( " TG [ " );
|
||||
sb.append( getTalkgroupID() );
|
||||
sb.append( "/" );
|
||||
sb.append( getTalkgroupIDAlias() );
|
||||
sb.append( " ] FREE:" );
|
||||
sb.append( format( getFree(), 2 ) );
|
||||
break;
|
||||
case CA_ENDD:
|
||||
sb.append( "END* AREA:" );
|
||||
sb.append( getArea() );
|
||||
sb.append( " LCN:" );
|
||||
sb.append( format( getChannel(), 2 ) );
|
||||
sb.append( " TG [" );
|
||||
sb.append( getTalkgroupID() );
|
||||
sb.append( "/" );
|
||||
sb.append( getTalkgroupIDAlias() );
|
||||
sb.append( "] FREE:" );
|
||||
sb.append( format( getFree(), 2 ) );
|
||||
break;
|
||||
case RQ_ACCE:
|
||||
sb.append( "REQUEST ACCESS LCN:" );
|
||||
sb.append( format( getChannel(), 2 ) );
|
||||
sb.append( " TG [ " );
|
||||
sb.append( getTalkgroupID() );
|
||||
sb.append( "/" );
|
||||
sb.append( getTalkgroupIDAlias() );
|
||||
sb.append( " ] FREE:" );
|
||||
sb.append( format( getFree(), 2 ) );
|
||||
break;
|
||||
case ID_ESNL:
|
||||
sb.append( "ESN LOW " );
|
||||
sb.append( getESN() );
|
||||
sb.append( "/" );
|
||||
sb.append( getESNAlias() );
|
||||
break;
|
||||
case ID_ESNH:
|
||||
sb.append( "ESN HIGH " );
|
||||
sb.append( getESN() );
|
||||
sb.append( "/" );
|
||||
sb.append( getESNAlias() );
|
||||
break;
|
||||
case ID_UNIQ:
|
||||
sb.append( "RADIO UNIQUE ID " );
|
||||
sb.append( getRadioUniqueID() );
|
||||
|
||||
if( getRadioUniqueIDAlias() != null )
|
||||
{
|
||||
sb.append( "/" );
|
||||
sb.append( getRadioUniqueIDAlias().getName() );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sb.append( "UNKNOWN " );
|
||||
sb.append( getArea() );
|
||||
sb.append( " " );
|
||||
sb.append( format( getChannel(), 2 ) );
|
||||
sb.append( " " );
|
||||
sb.append( format( getHomeRepeater(), 2 ) );
|
||||
sb.append( " " );
|
||||
sb.append( format( getGroup(), 3 ) );
|
||||
sb.append( " " );
|
||||
sb.append( format( getFree(), 2 ) );
|
||||
sb.append( " CRC:" );
|
||||
sb.append( CRCLTR.getTransmittedChecksum( mMessage ) );
|
||||
sb.append( " CALC:" );
|
||||
sb.append( CRCLTR.getCalculatedChecksum( mMessage ) );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getRadioUniqueID()
|
||||
{
|
||||
int retVal = INT_NULL_VALUE;
|
||||
|
||||
if( mMessageType == MessageType.ID_UNIQ )
|
||||
{
|
||||
retVal = getInt( sSIXTEEN_BITS );
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public Alias getRadioUniqueIDAlias()
|
||||
{
|
||||
if( mAliasList != null )
|
||||
{
|
||||
return mAliasList.getUniqueID( getRadioUniqueID() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public MessageType getMessageType()
|
||||
{
|
||||
MessageType retVal = MessageType.UN_KNWN;
|
||||
|
||||
int channel = getChannel();
|
||||
|
||||
if( channel == 31 )
|
||||
{
|
||||
retVal = MessageType.CA_ENDD;
|
||||
}
|
||||
else if( channel > 20 )
|
||||
{
|
||||
switch( channel )
|
||||
{
|
||||
case sCHIU_UNIQUE_ID:
|
||||
retVal = MessageType.ID_UNIQ;
|
||||
break;
|
||||
case sCHIU_ESN_LOW:
|
||||
retVal = MessageType.ID_ESNH;
|
||||
break;
|
||||
case sCHIU_ESN_HIGH:
|
||||
retVal = MessageType.ID_ESNL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( channel > 0 )
|
||||
{
|
||||
int free = getFree();
|
||||
|
||||
switch( free )
|
||||
{
|
||||
case sFREE_CALL:
|
||||
retVal = MessageType.CA_STRT;
|
||||
break;
|
||||
case sFREE_END_CALL:
|
||||
retVal = MessageType.CA_ENDD;
|
||||
break;
|
||||
case sFREE_REQUEST_ACCESS:
|
||||
retVal = MessageType.RQ_ACCE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
@Override
|
||||
public String getFromID()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuxiliaryMessage( LTRNetOSWMessage message )
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plottable getPlottable()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a listing of aliases contained in the message.
|
||||
*/
|
||||
public List<Alias> getAliases()
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<Alias>();
|
||||
|
||||
Alias from = getFromIDAlias();
|
||||
|
||||
if( from != null )
|
||||
{
|
||||
aliases.add( from );
|
||||
}
|
||||
|
||||
Alias to = getToIDAlias();
|
||||
|
||||
if( to != null )
|
||||
{
|
||||
aliases.add( to );
|
||||
}
|
||||
|
||||
Alias esn = getESNAlias();
|
||||
|
||||
if( esn != null )
|
||||
{
|
||||
aliases.add( esn );
|
||||
}
|
||||
|
||||
return aliases;
|
||||
}
|
||||
}
|
||||
243
src/module/decode/ltrnet/LTRNetMessage.java
Normal file
243
src/module/decode/ltrnet/LTRNetMessage.java
Normal file
@@ -0,0 +1,243 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 module.decode.ltrnet;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import message.Message;
|
||||
import message.MessageDirection;
|
||||
import message.MessageType;
|
||||
import module.decode.DecoderType;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
import edac.CRCLTR;
|
||||
|
||||
public abstract class LTRNetMessage extends Message
|
||||
{
|
||||
protected static final String sUNKNOWN = "**UNKNOWN**";
|
||||
protected static final int INT_NULL_VALUE = -1;
|
||||
protected static final double sDOUBLE_NULL_VALUE = -1.0D;
|
||||
protected SimpleDateFormat mDatestampFormatter =
|
||||
new SimpleDateFormat( "yyyyMMdd HHmmss" );
|
||||
protected DecimalFormat mDecimalFormatter = new DecimalFormat("0.00000");
|
||||
|
||||
protected static final int[] sSYNC = { 8,7,6,5,4,3,2,1,0 };
|
||||
protected static final int[] sAREA = { 9 };
|
||||
protected static final int[] sCHANNEL = { 14,13,12,11,10 };
|
||||
protected static final int[] sHOME_REPEATER = { 19,18,17,16,15 };
|
||||
protected static final int[] sGROUP = { 27,26,25,24,23,22,21,20 };
|
||||
protected static final int[] sFREE = { 32,31,30,29,28 };
|
||||
protected static final int[] sCRC = { 39,38,37,36,35,34,33 };
|
||||
protected static final int[] sSIXTEEN_BITS = { 32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17 };
|
||||
protected static final int[] sMANUFACTURER_ID = { 23,22,21,20,19,18,17 };
|
||||
|
||||
protected BinaryMessage mMessage;
|
||||
protected MessageType mMessageType;
|
||||
protected CRC mCRC;
|
||||
protected AliasList mAliasList;
|
||||
|
||||
public LTRNetMessage( BinaryMessage message,
|
||||
MessageDirection direction,
|
||||
AliasList list )
|
||||
{
|
||||
mMessage = message;
|
||||
mCRC = CRCLTR.check( message, direction );
|
||||
mAliasList = list;
|
||||
}
|
||||
|
||||
public MessageType getMessageType()
|
||||
{
|
||||
return mMessageType;
|
||||
}
|
||||
|
||||
public abstract void setAuxiliaryMessage( LTRNetOSWMessage message );
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
return mCRC != CRC.FAILED_CRC && mCRC != CRC.FAILED_PARITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends spaces to the end of the stringbuilder to make it length long
|
||||
*/
|
||||
protected void pad( StringBuilder sb, int length )
|
||||
{
|
||||
while( sb.length() < length )
|
||||
{
|
||||
sb.append( " " );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBinaryMessage()
|
||||
{
|
||||
return mMessage.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value formatted in hex notation.
|
||||
*
|
||||
* @param value - integer value
|
||||
* @return - hex digits returned
|
||||
*/
|
||||
protected static String getHex( int value, int digits )
|
||||
{
|
||||
return String.format( "%0" + digits + "X", value );
|
||||
}
|
||||
|
||||
protected int getInt( int[] bits )
|
||||
{
|
||||
int retVal = 0;
|
||||
|
||||
for( int x = 0; x < bits.length; x++ )
|
||||
{
|
||||
if( mMessage.get( bits[ x ] ) )
|
||||
{
|
||||
retVal += 1<<x;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads an integer value with additional zeroes to make it decimalPlaces long
|
||||
*/
|
||||
public String format( int number, int decimalPlaces )
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int paddingRequired = decimalPlaces - ( String.valueOf( number ).length() );
|
||||
|
||||
for( int x = 0; x < paddingRequired; x++)
|
||||
{
|
||||
sb.append( "0" );
|
||||
}
|
||||
|
||||
sb.append( number );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String format( String val, int places )
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( val );
|
||||
|
||||
while( sb.length() < places )
|
||||
{
|
||||
sb.append( " " );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public CRC getCRC()
|
||||
{
|
||||
return mCRC;
|
||||
}
|
||||
|
||||
public int getArea()
|
||||
{
|
||||
return getInt( sAREA );
|
||||
}
|
||||
|
||||
public int getChannel()
|
||||
{
|
||||
return getInt( sCHANNEL );
|
||||
}
|
||||
|
||||
public int getHomeRepeater()
|
||||
{
|
||||
return getInt( sHOME_REPEATER );
|
||||
}
|
||||
|
||||
public int getGroup()
|
||||
{
|
||||
return getInt( sGROUP );
|
||||
}
|
||||
|
||||
public String getTalkgroupID()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getArea() );
|
||||
sb.append( "-" );
|
||||
sb.append( format( getHomeRepeater(), 2 ) );
|
||||
sb.append( "-" );
|
||||
sb.append( format( getGroup(), 3 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Alias getTalkgroupIDAlias()
|
||||
{
|
||||
return mAliasList.getTalkgroupAlias( getTalkgroupID() );
|
||||
}
|
||||
|
||||
public int getFree()
|
||||
{
|
||||
return getInt( sFREE );
|
||||
}
|
||||
|
||||
public int getCRCChecksum()
|
||||
{
|
||||
return getInt( sCRC );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return DecoderType.LTR_NET.getDisplayString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
if( mMessageType != null )
|
||||
{
|
||||
return mMessageType.getDisplayText();
|
||||
}
|
||||
else
|
||||
{
|
||||
return MessageType.UN_KNWN.getDisplayText();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToID()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorStatus()
|
||||
{
|
||||
return mCRC.getDisplayText();
|
||||
}
|
||||
}
|
||||
80
src/module/decode/ltrnet/LTRNetMessageFilter.java
Normal file
80
src/module/decode/ltrnet/LTRNetMessageFilter.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package module.decode.ltrnet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import message.MessageType;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class LTRNetMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<MessageType, FilterElement<MessageType>> mElements =
|
||||
new HashMap<MessageType, FilterElement<MessageType>>();
|
||||
|
||||
public LTRNetMessageFilter()
|
||||
{
|
||||
super( "LTR-Net Message Filter" );
|
||||
|
||||
mElements.put( MessageType.CA_STRT,
|
||||
new FilterElement<MessageType>( MessageType.CA_STRT ) );
|
||||
mElements.put( MessageType.CA_ENDD,
|
||||
new FilterElement<MessageType>( MessageType.CA_ENDD ) );
|
||||
mElements.put( MessageType.SY_IDLE,
|
||||
new FilterElement<MessageType>( MessageType.SY_IDLE ) );
|
||||
mElements.put( MessageType.ID_UNIQ,
|
||||
new FilterElement<MessageType>( MessageType.ID_UNIQ ) );
|
||||
mElements.put( MessageType.ID_ESNH,
|
||||
new FilterElement<MessageType>( MessageType.ID_ESNH ) );
|
||||
mElements.put( MessageType.ID_ESNL,
|
||||
new FilterElement<MessageType>( MessageType.ID_ESNL ) );
|
||||
mElements.put( MessageType.RQ_ACCE,
|
||||
new FilterElement<MessageType>( MessageType.RQ_ACCE ) );
|
||||
mElements.put( MessageType.ID_SITE,
|
||||
new FilterElement<MessageType>( MessageType.ID_SITE ) );
|
||||
mElements.put( MessageType.FQ_RXHI,
|
||||
new FilterElement<MessageType>( MessageType.FQ_RXHI ) );
|
||||
mElements.put( MessageType.FQ_RXLO,
|
||||
new FilterElement<MessageType>( MessageType.FQ_RXLO ) );
|
||||
mElements.put( MessageType.FQ_TXHI,
|
||||
new FilterElement<MessageType>( MessageType.FQ_TXHI ) );
|
||||
mElements.put( MessageType.FQ_TXLO,
|
||||
new FilterElement<MessageType>( MessageType.FQ_TXLO ) );
|
||||
mElements.put( MessageType.ID_NBOR,
|
||||
new FilterElement<MessageType>( MessageType.ID_NBOR ) );
|
||||
mElements.put( MessageType.MA_CHNH,
|
||||
new FilterElement<MessageType>( MessageType.MA_CHNH ) );
|
||||
mElements.put( MessageType.MA_CHNL,
|
||||
new FilterElement<MessageType>( MessageType.MA_CHNL ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
LTRNetMessage ltr = (LTRNetMessage)message;
|
||||
|
||||
if( mElements.containsKey( ltr.getMessageType() ) )
|
||||
{
|
||||
return mElements.get( ltr.getMessageType() ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof LTRNetMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mElements.values() );
|
||||
}
|
||||
}
|
||||
167
src/module/decode/ltrnet/LTRNetMessageProcessor.java
Normal file
167
src/module/decode/ltrnet/LTRNetMessageProcessor.java
Normal file
@@ -0,0 +1,167 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 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 module.decode.ltrnet;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import message.Message;
|
||||
import message.MessageDirection;
|
||||
import message.MessageType;
|
||||
import sample.Listener;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
|
||||
public class LTRNetMessageProcessor implements Listener<BinaryMessage>
|
||||
{
|
||||
private Listener<Message> mMessageListener;
|
||||
|
||||
private HashMap<Integer,LTRNetOSWMessage> mReceiveHighAuxMessages =
|
||||
new HashMap<Integer,LTRNetOSWMessage>();
|
||||
private HashMap<Integer,LTRNetOSWMessage> mReceiveLowAuxMessages =
|
||||
new HashMap<Integer,LTRNetOSWMessage>();
|
||||
|
||||
private HashMap<Integer,LTRNetOSWMessage> mTransmitHighAuxMessages =
|
||||
new HashMap<Integer,LTRNetOSWMessage>();
|
||||
private HashMap<Integer,LTRNetOSWMessage> mTransmitLowAuxMessages =
|
||||
new HashMap<Integer,LTRNetOSWMessage>();
|
||||
|
||||
private LTRNetISWMessage mESNHighMessage;
|
||||
private LTRNetISWMessage mESNLowMessage;
|
||||
|
||||
private MessageDirection mDirection;
|
||||
private AliasList mAliasList;
|
||||
|
||||
public LTRNetMessageProcessor( MessageDirection direction,
|
||||
AliasList list )
|
||||
{
|
||||
mDirection = direction;
|
||||
mAliasList = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( BinaryMessage buffer )
|
||||
{
|
||||
if( mMessageListener != null )
|
||||
{
|
||||
LTRNetMessage message;
|
||||
|
||||
if( mDirection == MessageDirection.OSW )
|
||||
{
|
||||
message = new LTRNetOSWMessage( buffer, mAliasList );
|
||||
|
||||
if( message.isValid() )
|
||||
{
|
||||
if( message.getMessageType() == MessageType.FQ_TXHI )
|
||||
{
|
||||
mTransmitHighAuxMessages.put( message.getHomeRepeater(),
|
||||
(LTRNetOSWMessage)message );
|
||||
|
||||
message.setAuxiliaryMessage( mTransmitLowAuxMessages.get(
|
||||
message.getHomeRepeater() ) );
|
||||
}
|
||||
else if( message.getMessageType() == MessageType.FQ_TXLO )
|
||||
{
|
||||
mTransmitLowAuxMessages.put( message.getHomeRepeater(),
|
||||
(LTRNetOSWMessage)message );
|
||||
|
||||
message.setAuxiliaryMessage( mTransmitHighAuxMessages.get(
|
||||
message.getHomeRepeater() ) );
|
||||
}
|
||||
else if( message.getMessageType() == MessageType.FQ_RXHI )
|
||||
{
|
||||
mReceiveHighAuxMessages.put( message.getHomeRepeater(),
|
||||
(LTRNetOSWMessage)message );
|
||||
|
||||
message.setAuxiliaryMessage( mReceiveLowAuxMessages.get(
|
||||
message.getHomeRepeater() ) );
|
||||
}
|
||||
else if( message.getMessageType() == MessageType.FQ_RXLO )
|
||||
{
|
||||
mReceiveLowAuxMessages.put( message.getHomeRepeater(),
|
||||
(LTRNetOSWMessage)message );
|
||||
message.setAuxiliaryMessage( mReceiveHighAuxMessages.get(
|
||||
message.getHomeRepeater() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.flip( 0, 40 );
|
||||
|
||||
message = new LTRNetISWMessage( buffer, mAliasList );
|
||||
|
||||
if( message.isValid() )
|
||||
{
|
||||
/**
|
||||
* Catch ESN High messages to marry up with ESN Low messages. Purge
|
||||
* the ESN high message after 2 messages, so that it doesn't get
|
||||
* paired with the wrong esn low message
|
||||
*/
|
||||
if( message.getMessageType() == MessageType.ID_ESNH )
|
||||
{
|
||||
mESNHighMessage = (LTRNetISWMessage)message;
|
||||
|
||||
if( mESNLowMessage != null )
|
||||
{
|
||||
/* Check that the stored message is not older than
|
||||
* 5 seconds */
|
||||
if( System.currentTimeMillis() -
|
||||
mESNLowMessage.getTimeReceived() < 5000 )
|
||||
{
|
||||
((LTRNetISWMessage)message).setAuxiliaryMessage( mESNLowMessage );
|
||||
}
|
||||
else
|
||||
{
|
||||
mESNLowMessage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( message.getMessageType() == MessageType.ID_ESNL )
|
||||
{
|
||||
mESNLowMessage = (LTRNetISWMessage)message;
|
||||
|
||||
if( mESNHighMessage != null )
|
||||
{
|
||||
/* Check that the stored message is not older than 5 seconds */
|
||||
if( System.currentTimeMillis() - mESNHighMessage.getTimeReceived() < 5000 )
|
||||
{
|
||||
((LTRNetISWMessage)message).setAuxiliaryMessage( mESNHighMessage );
|
||||
}
|
||||
else
|
||||
{
|
||||
mESNHighMessage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mMessageListener.receive( message );
|
||||
}
|
||||
}
|
||||
|
||||
public void setMessageListener( Listener<Message> listener )
|
||||
{
|
||||
mMessageListener = listener;
|
||||
}
|
||||
|
||||
public void removeMessageListener()
|
||||
{
|
||||
mMessageListener = null;
|
||||
}
|
||||
}
|
||||
644
src/module/decode/ltrnet/LTRNetOSWMessage.java
Normal file
644
src/module/decode/ltrnet/LTRNetOSWMessage.java
Normal file
@@ -0,0 +1,644 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 module.decode.ltrnet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import map.Plottable;
|
||||
import message.MessageDirection;
|
||||
import message.MessageType;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
|
||||
public class LTRNetOSWMessage extends LTRNetMessage
|
||||
{
|
||||
private static final int CHANNEL_FREQUENCY_MESSAGE_TYPE_BIT = 20;
|
||||
private static final int CHANNEL_MAP_MESSAGE_TYPE_BIT = 17;
|
||||
|
||||
private static final int CHIU_UNIQUE_ID = 17;
|
||||
private static final int CHIU_SITE_ID = 18;
|
||||
private static final int CHIU_TRANSMIT_FREQUENCY = 24;
|
||||
private static final int CHIU_RECEIVE_FREQUENCY = 25;
|
||||
private static final int CHIU_NEIGHBOR = 26;
|
||||
private static final int CHIU_MAP = 28;
|
||||
private static final int CHIU_CALL_END = 31;
|
||||
|
||||
private static final int HOME_DIRECTED_GROUP_CALL = 29;
|
||||
private static final int HOME_CHANNEL_IN_USE_MUTE_AUDIO = 30;
|
||||
|
||||
private static final int GROUP_DO_NOTHING = 253;
|
||||
private static final int GROUP_CWID = 254;
|
||||
private static final int GROUP_CHANNEL_IDLE = 255;
|
||||
|
||||
private static final int FREE_ALL_CHANNELS_BUSY = 0;
|
||||
private static final int FREE_LTR_GROUP_CALL = 30;
|
||||
private static final int FREE_LTRNET_GROUP_CALL = 31;
|
||||
|
||||
private LTRNetOSWMessage mAuxMessage;
|
||||
|
||||
public LTRNetOSWMessage( BinaryMessage message, AliasList list )
|
||||
{
|
||||
super( message, MessageDirection.OSW, list );
|
||||
mMessageType = getType();
|
||||
}
|
||||
|
||||
public void setAuxiliaryMessage( LTRNetOSWMessage message )
|
||||
{
|
||||
if( message != null )
|
||||
{
|
||||
mAuxMessage = message;
|
||||
}
|
||||
}
|
||||
|
||||
public String getRadioUniqueIDText()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int radioId = getRadioUniqueID();
|
||||
|
||||
if( radioId != INT_NULL_VALUE )
|
||||
{
|
||||
sb.append( " RADIO UNIQUE ID: " );
|
||||
sb.append( radioId );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( mDatestampFormatter.format(
|
||||
new Date( System.currentTimeMillis() ) ) );
|
||||
sb.append( " LTRNet OSW [" );
|
||||
sb.append( mCRC.getAbbreviation() );
|
||||
sb.append( "] " );
|
||||
sb.append( getMessage() );
|
||||
pad( sb, 100 );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
switch( mMessageType )
|
||||
{
|
||||
case SY_IDLE:
|
||||
sb.append( "IDLE AREA:" );
|
||||
sb.append( getArea() );
|
||||
sb.append( " LCN:" );
|
||||
sb.append( format( getChannel(), 2 ) );
|
||||
sb.append( " HOME:" );
|
||||
sb.append( format( getHomeRepeater(), 2 ) );
|
||||
sb.append( " GRP:" );
|
||||
sb.append( format( getGroup(), 3 ) );
|
||||
sb.append( " FREE:" );
|
||||
sb.append( format( getFree(), 2 ) );
|
||||
break;
|
||||
case CA_STRT:
|
||||
sb.append( "CALL LCN:" );
|
||||
sb.append( format( getChannel(), 2 ) );
|
||||
sb.append( " TG [ " );
|
||||
sb.append( getTalkgroupID() );
|
||||
sb.append( "/" );
|
||||
sb.append( getTalkgroupIDAlias() );
|
||||
sb.append( " ] FREE:" );
|
||||
sb.append( format( getFree(), 2 ) );
|
||||
break;
|
||||
case CA_ENDD:
|
||||
sb.append( "END* AREA:" );
|
||||
sb.append( getArea() );
|
||||
sb.append( " LCN:" );
|
||||
sb.append( format( getChannel(), 2 ) );
|
||||
sb.append( " TG [" );
|
||||
sb.append( getTalkgroupID() );
|
||||
sb.append( "/" );
|
||||
sb.append( getTalkgroupIDAlias() );
|
||||
sb.append( "] FREE:" );
|
||||
sb.append( format( getFree(), 2 ) );
|
||||
break;
|
||||
case MA_CHNL:
|
||||
sb.append( "CHAN MAP LOW LCN [" );
|
||||
sb.append( getChannelMapAsString( getChannelMapLow() ) );
|
||||
sb.append( "]" );
|
||||
break;
|
||||
case MA_CHNH:
|
||||
sb.append( "CHAN MAP HIGH LCN [" );
|
||||
sb.append( getChannelMapAsString( getChannelMapHigh() ) );
|
||||
sb.append( "]" );
|
||||
break;
|
||||
case FQ_RXLO:
|
||||
sb.append( "CHAN RX LOW LCN:" );
|
||||
sb.append( format( getHomeRepeater(), 2 ) );
|
||||
sb.append( " = " );
|
||||
long rxFreqLo = getFrequency();
|
||||
if( rxFreqLo > 0 )
|
||||
{
|
||||
sb.append( mDecimalFormatter.format( (double)rxFreqLo / 1E6d ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "000.00000" );
|
||||
}
|
||||
sb.append( " MHz" );
|
||||
break;
|
||||
case FQ_RXHI:
|
||||
sb.append( "CHAN RX HIGH LCN:" );
|
||||
sb.append( format( getHomeRepeater(), 2 ) );
|
||||
sb.append( " = " );
|
||||
long rxfreqhi = getFrequency();
|
||||
if( rxfreqhi > 0 )
|
||||
{
|
||||
sb.append( mDecimalFormatter.format( (double)rxfreqhi / 1E6d ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "000.00000" );
|
||||
}
|
||||
sb.append( " MHz" );
|
||||
break;
|
||||
case FQ_TXHI:
|
||||
sb.append( "CHAN TX LOW LCN:" );
|
||||
sb.append( format( getHomeRepeater(), 2 ) );
|
||||
sb.append( " = " );
|
||||
long txfreq = getFrequency();
|
||||
if( txfreq > 0 )
|
||||
{
|
||||
sb.append( mDecimalFormatter.format( (double)txfreq / 1E6d ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "000.00000" );
|
||||
}
|
||||
sb.append( " MHz" );
|
||||
break;
|
||||
case FQ_TXLO:
|
||||
sb.append( "CHAN TX HIGH LCN:" );
|
||||
sb.append( format( getHomeRepeater(), 2 ) );
|
||||
sb.append( " = " );
|
||||
long txFreqLo = getFrequency();
|
||||
if( txFreqLo > 0 )
|
||||
{
|
||||
sb.append( mDecimalFormatter.format( (double)txFreqLo / 1E6d ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "000.00000" );
|
||||
}
|
||||
sb.append( " MHz" );
|
||||
break;
|
||||
case ID_SITE:
|
||||
String siteId = getSiteID();
|
||||
if( siteId != null )
|
||||
{
|
||||
sb.append( "SITE ID: " );
|
||||
sb.append( siteId );
|
||||
sb.append( " " );
|
||||
sb.append( getSiteIDAlias() );
|
||||
}
|
||||
break;
|
||||
case ID_NBOR:
|
||||
int neighborRank = getNeighborRank();
|
||||
String neighborId = getNeighborID();
|
||||
|
||||
if( neighborRank != INT_NULL_VALUE &&
|
||||
neighborId != null )
|
||||
{
|
||||
sb.append( "NEIGHBOR SITE " );
|
||||
sb.append( neighborRank );
|
||||
sb.append( ": " );
|
||||
sb.append( neighborId );
|
||||
sb.append( " " );
|
||||
sb.append( getNeighborIDAlias() );
|
||||
}
|
||||
break;
|
||||
case ID_UNIQ:
|
||||
sb.append( "REGISTER RADIO UNIQUE ID:" );
|
||||
sb.append( getRadioUniqueID() );
|
||||
break;
|
||||
default:
|
||||
sb.append( "UNKNOWN " );
|
||||
sb.append( getArea() );
|
||||
sb.append( " " + format( getChannel(), 2 ) );
|
||||
sb.append( " " + format( getHomeRepeater(), 2 ) );
|
||||
sb.append( " " + format( getGroup(), 3 ) );
|
||||
sb.append( " " + format( getFree(), 2 ) );
|
||||
sb.append( " A:" );
|
||||
sb.append( getArea() );
|
||||
sb.append( " C:" );
|
||||
sb.append( format( getChannel(), 2 ) );
|
||||
sb.append( " H:" );
|
||||
sb.append( format( getHomeRepeater(), 2 ) );
|
||||
sb.append( " G:" );
|
||||
sb.append( format( getGroup(), 3 ) );
|
||||
sb.append( " F:" );
|
||||
sb.append( format( getFree(), 2 ) );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTalkgroupID()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getArea() );
|
||||
sb.append( "-" );
|
||||
sb.append( format( getHomeRepeater(), 2 ) );
|
||||
sb.append( "-" );
|
||||
sb.append( format( getGroup(), 3 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Alias getTalkgroupIDAlias()
|
||||
{
|
||||
if( mAliasList != null )
|
||||
{
|
||||
return mAliasList.getTalkgroupAlias( getTalkgroupID() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getChannelMapLow()
|
||||
{
|
||||
ArrayList<Integer> retVal = new ArrayList<Integer>();
|
||||
|
||||
if( mMessageType == MessageType.MA_CHNL )
|
||||
{
|
||||
for( int x = 27; x >= 18; x-- )
|
||||
{
|
||||
if( mMessage.get( x ) )
|
||||
{
|
||||
retVal.add( 28 - x );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getChannelMapHigh()
|
||||
{
|
||||
ArrayList<Integer> retVal = new ArrayList<Integer>();
|
||||
|
||||
if( mMessageType == MessageType.MA_CHNH )
|
||||
{
|
||||
for( int x = 27; x >= 18; x-- )
|
||||
{
|
||||
if( mMessage.get( x ) )
|
||||
{
|
||||
retVal.add( 38 - x );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public String getChannelMapAsString( ArrayList<Integer> channels )
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for( Integer channel: channels )
|
||||
{
|
||||
sb.append( channel );
|
||||
sb.append( " " );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getRadioUniqueID()
|
||||
{
|
||||
int retVal = INT_NULL_VALUE;
|
||||
|
||||
if( mMessageType == MessageType.ID_UNIQ )
|
||||
{
|
||||
retVal = mMessage.getInt( 17, 32 );
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public Alias getRadioUniqueIDAlias()
|
||||
{
|
||||
if( mAliasList != null )
|
||||
{
|
||||
return mAliasList.getUniqueID( getRadioUniqueID() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
if( mMessageType == MessageType.ID_SITE )
|
||||
{
|
||||
return String.valueOf( mMessage.getInt( 23, 32 ) );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Alias getSiteIDAlias()
|
||||
{
|
||||
if( mAliasList != null )
|
||||
{
|
||||
return mAliasList.getSiteID( getSiteID() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getNeighborID()
|
||||
{
|
||||
if( mMessageType == MessageType.ID_NBOR )
|
||||
{
|
||||
int id = mMessage.getInt( 23, 32 );
|
||||
|
||||
if( id > 0 )
|
||||
{
|
||||
return String.valueOf( id );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Alias getNeighborIDAlias()
|
||||
{
|
||||
if( mAliasList != null )
|
||||
{
|
||||
return mAliasList.getSiteID( getNeighborID() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getNeighborRank()
|
||||
{
|
||||
int retVal = INT_NULL_VALUE;
|
||||
|
||||
if( mMessageType == MessageType.ID_NBOR )
|
||||
{
|
||||
retVal = mMessage.getInt( 15, 18 ) + 1;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public long getFrequency()
|
||||
{
|
||||
long retVal = 0;
|
||||
|
||||
if( mAuxMessage != null )
|
||||
{
|
||||
int high;
|
||||
int low;
|
||||
|
||||
MessageType type = getMessageType();
|
||||
|
||||
if( type == MessageType.FQ_RXHI || type == MessageType.FQ_TXHI )
|
||||
{
|
||||
high = getHighChannelUnits();
|
||||
low = mAuxMessage.getLowChannelUnits();
|
||||
}
|
||||
else
|
||||
{
|
||||
high = mAuxMessage.getHighChannelUnits();
|
||||
low = getLowChannelUnits();
|
||||
}
|
||||
|
||||
if( high != INT_NULL_VALUE && low != INT_NULL_VALUE )
|
||||
{
|
||||
retVal = ( high + low ) * 1250 + 150000000;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the high order (15 - 12) frequency bits which are
|
||||
* the lower 4 bits of the Free field, left shifted by 12, representing the
|
||||
* frequency value in units of .00125 MHz
|
||||
*/
|
||||
public int getHighChannelUnits()
|
||||
{
|
||||
int retVal = INT_NULL_VALUE;
|
||||
|
||||
if( mAuxMessage != null &&
|
||||
( mMessageType == MessageType.FQ_RXHI ||
|
||||
mMessageType == MessageType.FQ_TXHI ) )
|
||||
{
|
||||
retVal = mMessage.getInt( 29, 32 );
|
||||
|
||||
retVal = Integer.rotateLeft( retVal, 12 );
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the low order (11 - 0) frequency bits which are
|
||||
* contained in the Group and Free fields representing the frequency value
|
||||
* units of .00125 MHz
|
||||
*/
|
||||
public int getLowChannelUnits()
|
||||
{
|
||||
int retVal = INT_NULL_VALUE;
|
||||
|
||||
if( mMessageType == MessageType.FQ_RXLO ||
|
||||
mMessageType == MessageType.FQ_TXLO )
|
||||
{
|
||||
retVal = mMessage.getInt( 21, 32 );
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public MessageType getType()
|
||||
{
|
||||
MessageType retVal = MessageType.UN_KNWN;
|
||||
|
||||
int channel = getChannel();
|
||||
|
||||
int home = getHomeRepeater();
|
||||
|
||||
//LTR-Net messages
|
||||
if( home != 31 && ( channel > 20 || home > 20 ) )
|
||||
{
|
||||
switch( channel )
|
||||
{
|
||||
case CHIU_UNIQUE_ID:
|
||||
retVal = MessageType.ID_UNIQ;
|
||||
break;
|
||||
case CHIU_SITE_ID:
|
||||
retVal = MessageType.ID_SITE;
|
||||
break;
|
||||
case CHIU_TRANSMIT_FREQUENCY:
|
||||
if( getHomeRepeater() == 24 )
|
||||
{
|
||||
retVal = MessageType.ID_UNIQ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mMessage.get( CHANNEL_FREQUENCY_MESSAGE_TYPE_BIT ) )
|
||||
{
|
||||
retVal = MessageType.FQ_TXHI;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = MessageType.FQ_TXLO;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHIU_RECEIVE_FREQUENCY:
|
||||
if( mMessage.get( CHANNEL_FREQUENCY_MESSAGE_TYPE_BIT ) )
|
||||
{
|
||||
retVal = MessageType.FQ_RXHI;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = MessageType.FQ_RXLO;
|
||||
}
|
||||
break;
|
||||
case CHIU_NEIGHBOR:
|
||||
retVal = MessageType.ID_NBOR;
|
||||
break;
|
||||
case CHIU_MAP:
|
||||
if( mMessage.get( CHANNEL_MAP_MESSAGE_TYPE_BIT ) )
|
||||
{
|
||||
retVal = MessageType.MA_CHNH;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = MessageType.MA_CHNL;
|
||||
}
|
||||
break;
|
||||
case CHIU_CALL_END:
|
||||
retVal = MessageType.CA_ENDD;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int group = getGroup();
|
||||
|
||||
if( group == GROUP_CHANNEL_IDLE )
|
||||
{
|
||||
retVal = MessageType.SY_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = MessageType.CA_STRT;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFromID()
|
||||
{
|
||||
if( mMessageType == MessageType.CA_STRT ||
|
||||
mMessageType == MessageType.CA_ENDD )
|
||||
{
|
||||
return getTalkgroupID();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
if( mMessageType == MessageType.CA_STRT ||
|
||||
mMessageType == MessageType.CA_ENDD )
|
||||
{
|
||||
return getTalkgroupIDAlias();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plottable getPlottable()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a listing of aliases contained in the message.
|
||||
*/
|
||||
public List<Alias> getAliases()
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<Alias>();
|
||||
|
||||
Alias from = getFromIDAlias();
|
||||
|
||||
if( from != null )
|
||||
{
|
||||
aliases.add( from );
|
||||
}
|
||||
|
||||
Alias to = getToIDAlias();
|
||||
|
||||
if( to != null )
|
||||
{
|
||||
aliases.add( to );
|
||||
}
|
||||
|
||||
Alias neighbor = getNeighborIDAlias();
|
||||
|
||||
if( neighbor != null )
|
||||
{
|
||||
aliases.add( neighbor );
|
||||
}
|
||||
|
||||
Alias uid = getRadioUniqueIDAlias();
|
||||
|
||||
if( uid != null )
|
||||
{
|
||||
aliases.add( uid );
|
||||
}
|
||||
|
||||
Alias site = getSiteIDAlias();
|
||||
|
||||
if( site != null )
|
||||
{
|
||||
aliases.add( site );
|
||||
}
|
||||
|
||||
return aliases;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user