mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-13 00:57:31 -05:00
Updates pull request from Roman Tsypuk to convert the build system from
ant to gradle. Removes linux and windows application launch scripts and produces an executable jar with all resources included.
This commit is contained in:
@@ -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 io.github.dsheirer.module.decode.ltrstandard;
|
||||
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
||||
public class DecodeConfigLTRStandard extends DecodeConfiguration
|
||||
{
|
||||
private MessageDirection mMessageDirection = MessageDirection.OSW;
|
||||
|
||||
public DecodeConfigLTRStandard()
|
||||
{
|
||||
super( DecoderType.LTR_STANDARD );
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "direction" )
|
||||
public MessageDirection getMessageDirection()
|
||||
{
|
||||
return mMessageDirection;
|
||||
}
|
||||
|
||||
public void setMessageDirection( MessageDirection direction )
|
||||
{
|
||||
mMessageDirection = direction;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*******************************************************************************
|
||||
* 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 io.github.dsheirer.module.decode.ltrstandard;
|
||||
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.bits.MessageFramer;
|
||||
import io.github.dsheirer.bits.SyncPattern;
|
||||
import io.github.dsheirer.dsp.fsk.LTRFSKDecoder;
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.module.decode.Decoder;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.real.IUnFilteredRealBufferListener;
|
||||
import io.github.dsheirer.sample.real.RealBuffer;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
public class LTRStandardDecoder extends Decoder implements IUnFilteredRealBufferListener
|
||||
{
|
||||
public static final int LTR_STANDARD_MESSAGE_LENGTH = 40;
|
||||
|
||||
private LTRFSKDecoder mLTRFSKDecoder;
|
||||
private MessageFramer mLTRMessageFramer;
|
||||
private LTRStandardMessageProcessor mLTRMessageProcessor;
|
||||
|
||||
/**
|
||||
* LTR Decoder. Decodes unfiltered (e.g. demodulated but with no DC or
|
||||
* audio filtering) samples and produces LTR Standard messages.
|
||||
*/
|
||||
public LTRStandardDecoder( AliasList aliasList,
|
||||
MessageDirection direction )
|
||||
{
|
||||
mLTRFSKDecoder = new LTRFSKDecoder();
|
||||
|
||||
if( direction == 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 LTRStandardMessageProcessor( direction, aliasList );
|
||||
mLTRMessageFramer.addMessageListener( mLTRMessageProcessor );
|
||||
mLTRMessageProcessor.setMessageListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.LTR_STANDARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getUnFilteredRealBufferListener()
|
||||
{
|
||||
return mLTRFSKDecoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
mLTRMessageFramer.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.ltrstandard;
|
||||
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.gui.editor.Editor;
|
||||
import io.github.dsheirer.gui.editor.EditorValidationException;
|
||||
import io.github.dsheirer.gui.editor.ValidatingEditor;
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class LTRStandardDecoderEditor extends ValidatingEditor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JCheckBox mAFC;
|
||||
private JSlider mAFCMaximumCorrection;
|
||||
private JComboBox<MessageDirection> mComboDirection;
|
||||
|
||||
public LTRStandardDecoderEditor()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) );
|
||||
|
||||
mAFC = new JCheckBox( "AFC: 3000 Hz" );
|
||||
mAFC.setEnabled( false );
|
||||
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
|
||||
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
|
||||
mAFC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
setModified( true );
|
||||
|
||||
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( true );
|
||||
}
|
||||
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mAFC );
|
||||
|
||||
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
|
||||
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
|
||||
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
|
||||
mAFCMaximumCorrection.setPaintTicks( true );
|
||||
|
||||
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
add( mAFCMaximumCorrection );
|
||||
|
||||
mComboDirection = new JComboBox<MessageDirection>();
|
||||
mComboDirection.setModel( new DefaultComboBoxModel<MessageDirection>( MessageDirection.values() ) );
|
||||
mComboDirection.setSelectedItem( MessageDirection.OSW );
|
||||
mComboDirection.setEnabled( false );
|
||||
mComboDirection.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Format:" ) );
|
||||
add( mComboDirection );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate( Editor<Channel> editor ) throws EditorValidationException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel item )
|
||||
{
|
||||
super.setItem( item );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
mAFC.setEnabled( true );
|
||||
mComboDirection.setEnabled( true );
|
||||
|
||||
DecodeConfiguration config = getItem().getDecodeConfiguration();
|
||||
|
||||
if( config instanceof DecodeConfigLTRStandard )
|
||||
{
|
||||
DecodeConfigLTRStandard ltr = (DecodeConfigLTRStandard)config;
|
||||
mComboDirection.setSelectedItem( ltr.getMessageDirection() );
|
||||
mAFC.setSelected( ltr.isAFCEnabled() );
|
||||
mAFCMaximumCorrection.setValue( ltr.getAFCMaximumCorrection() );
|
||||
mAFCMaximumCorrection.setEnabled( ltr.isAFCEnabled() );
|
||||
setModified( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboDirection.setSelectedItem( MessageDirection.OSW );
|
||||
mAFC.setSelected( false );
|
||||
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
|
||||
setModified( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mAFC.setEnabled( false );
|
||||
mComboDirection.setEnabled( false );
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && isModified() )
|
||||
{
|
||||
DecodeConfigLTRStandard ltr = new DecodeConfigLTRStandard();
|
||||
|
||||
ltr.setAFC( mAFC.isSelected() );
|
||||
ltr.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
|
||||
ltr.setMessageDirection( (MessageDirection)mComboDirection.getSelectedItem() );
|
||||
|
||||
getItem().setDecodeConfiguration( ltr );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,482 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.ltrstandard;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
import io.github.dsheirer.channel.metadata.AliasedStringAttributeMonitor;
|
||||
import io.github.dsheirer.channel.metadata.Attribute;
|
||||
import io.github.dsheirer.channel.metadata.AttributeChangeRequest;
|
||||
import io.github.dsheirer.channel.state.DecoderState;
|
||||
import io.github.dsheirer.channel.state.DecoderStateEvent;
|
||||
import io.github.dsheirer.channel.state.DecoderStateEvent.Event;
|
||||
import io.github.dsheirer.channel.state.State;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.event.CallEvent;
|
||||
import io.github.dsheirer.module.decode.ltrnet.LTRCallEvent;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.message.CallEndMessage;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.message.CallMessage;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.message.IdleMessage;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.message.LTRStandardMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
public class LTRStandardDecoderState extends DecoderState
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger(LTRStandardDecoderState.class);
|
||||
|
||||
private Map<Integer,LTRCallEvent> mActiveCalls = new HashMap<>();
|
||||
private Set<String> mTalkgroupsFirstHeard = new HashSet<>();
|
||||
private Set<String> mTalkgroups = new TreeSet<>();
|
||||
|
||||
private AliasedStringAttributeMonitor mTalkgroupAttribute;
|
||||
private long mFrequency;
|
||||
private LCNTracker mLCNTracker = new LCNTracker();
|
||||
|
||||
public LTRStandardDecoderState(AliasList aliasList)
|
||||
{
|
||||
super(aliasList);
|
||||
|
||||
mTalkgroupAttribute = new AliasedStringAttributeMonitor(Attribute.PRIMARY_ADDRESS_TO,
|
||||
getAttributeChangeRequestListener(), getAliasList(), AliasIDType.TALKGROUP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.LTR_STANDARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(ScheduledExecutorService executor)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Message message)
|
||||
{
|
||||
if(message.isValid() && message instanceof LTRStandardMessage)
|
||||
{
|
||||
switch(((LTRStandardMessage) message).getMessageType())
|
||||
{
|
||||
case CA_STRT:
|
||||
CallMessage start = (CallMessage) message;
|
||||
|
||||
int channel = start.getChannel();
|
||||
|
||||
setChannelNumber(channel);
|
||||
|
||||
mLCNTracker.processFreeChannel(start.getFree());
|
||||
|
||||
//Only process calls on this LCN, or call detects for
|
||||
//talkgroups that are homed on this LCN
|
||||
if(mLCNTracker.isValidChannel(channel) &&
|
||||
(mLCNTracker.isCurrentChannel(channel) ||
|
||||
mLCNTracker.isCurrentChannel(start.getHomeRepeater())))
|
||||
{
|
||||
LTRCallEvent event = mActiveCalls.get(channel);
|
||||
|
||||
if(event == null || !event.isMatchingTalkgroup(start.getToID()))
|
||||
{
|
||||
//Check for different talkgroup
|
||||
if(event != null)
|
||||
{
|
||||
event.end();
|
||||
mActiveCalls.remove(channel);
|
||||
}
|
||||
|
||||
boolean current = mLCNTracker.isCurrentChannel(channel);
|
||||
|
||||
event = new LTRCallEvent.Builder(
|
||||
DecoderType.LTR_STANDARD,
|
||||
current ? CallEvent.CallEventType.CALL : CallEvent.CallEventType.CALL_DETECT)
|
||||
.to(start.getToID())
|
||||
.aliasList(getAliasList())
|
||||
.channel(start.getChannelFormatted())
|
||||
.frequency(current ? mFrequency : 0)
|
||||
.build();
|
||||
|
||||
mActiveCalls.put(channel, event);
|
||||
|
||||
broadcast(event);
|
||||
|
||||
if(mLCNTracker.isCurrentChannel(channel))
|
||||
{
|
||||
String talkgroup = start.getToID();
|
||||
mTalkgroupAttribute.process(talkgroup);
|
||||
processTalkgroup(talkgroup);
|
||||
}
|
||||
}
|
||||
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CALL));
|
||||
}
|
||||
break;
|
||||
case CA_ENDD:
|
||||
CallEndMessage end = (CallEndMessage) message;
|
||||
|
||||
//Home channel is 31 for call end -- use the free channel
|
||||
//as the call end channel
|
||||
int repeater = end.getFree();
|
||||
|
||||
setChannelNumber(repeater);
|
||||
|
||||
if(mLCNTracker.isCurrentChannel(repeater))
|
||||
{
|
||||
String talkgroup = end.getToID();
|
||||
mTalkgroupAttribute.process(talkgroup);
|
||||
processTalkgroup(talkgroup);
|
||||
|
||||
LTRCallEvent event = mActiveCalls.remove(repeater);
|
||||
|
||||
if(event != null)
|
||||
{
|
||||
event.end();
|
||||
broadcast(event);
|
||||
broadcast(new DecoderStateEvent(this, Event.END, State.FADE));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SY_IDLE:
|
||||
IdleMessage idle = (IdleMessage) message;
|
||||
|
||||
int lcn = idle.getChannel();
|
||||
|
||||
mLCNTracker.processCallChannel(lcn);
|
||||
|
||||
break;
|
||||
case UN_KNWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processTalkgroup(String talkgroup)
|
||||
{
|
||||
if(mTalkgroupsFirstHeard.contains(talkgroup))
|
||||
{
|
||||
mTalkgroups.add(talkgroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
mTalkgroupsFirstHeard.add(talkgroup);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a full reset
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
mActiveCalls.clear();
|
||||
mTalkgroupsFirstHeard.clear();
|
||||
mTalkgroups.clear();
|
||||
mLCNTracker.reset();
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a temporal reset following a call or other decode event
|
||||
*/
|
||||
private void resetState()
|
||||
{
|
||||
for(Integer key : mActiveCalls.keySet())
|
||||
{
|
||||
LTRCallEvent event = mActiveCalls.get(key);
|
||||
|
||||
if(event != null)
|
||||
{
|
||||
event.end();
|
||||
|
||||
broadcast(event);
|
||||
}
|
||||
}
|
||||
|
||||
mActiveCalls.clear();
|
||||
|
||||
mTalkgroupAttribute.reset();
|
||||
}
|
||||
|
||||
public boolean hasChannelNumber()
|
||||
{
|
||||
return mLCNTracker.getCurrentChannel() != 0;
|
||||
}
|
||||
|
||||
public int getChannelNumber()
|
||||
{
|
||||
return mLCNTracker.getCurrentChannel();
|
||||
}
|
||||
|
||||
private void setChannelNumber(int channel)
|
||||
{
|
||||
int original = mLCNTracker.getCurrentChannel();
|
||||
|
||||
mLCNTracker.processCallChannel(channel);
|
||||
|
||||
if(mLCNTracker.getCurrentChannel() != original)
|
||||
{
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.CHANNEL_FREQUENCY_LABEL,
|
||||
"LCN:" + mLCNTracker.getCurrentChannel()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveDecoderStateEvent(DecoderStateEvent event)
|
||||
{
|
||||
switch(event.getEvent())
|
||||
{
|
||||
case RESET:
|
||||
resetState();
|
||||
break;
|
||||
case SOURCE_FREQUENCY:
|
||||
mFrequency = event.getFrequency();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActivitySummary()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("Activity Summary\n\n");
|
||||
|
||||
sb.append("Decoder:\tLTR-Standard\n");
|
||||
|
||||
sb.append("Monitored LCN: ");
|
||||
|
||||
if(hasChannelNumber())
|
||||
{
|
||||
sb.append(getChannelNumber());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("*Insufficient Data*");
|
||||
}
|
||||
|
||||
sb.append("\n");
|
||||
|
||||
sb.append("Active LCNs:\t");
|
||||
|
||||
List<Integer> lcns = mLCNTracker.getActiveLCNs();
|
||||
|
||||
if(lcns.size() > 0)
|
||||
{
|
||||
sb.append(mLCNTracker.getActiveLCNs());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("*Insufficient Data*");
|
||||
}
|
||||
sb.append("\n\n");
|
||||
|
||||
sb.append("Talkgroups\n");
|
||||
|
||||
if(mTalkgroups.isEmpty())
|
||||
{
|
||||
sb.append(" None\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(String talkgroup : mTalkgroups)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(talkgroup);
|
||||
sb.append(" ");
|
||||
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias alias = getAliasList().getTalkgroupAlias(talkgroup);
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
sb.append(alias.getName());
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("\n");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks the set of call and free channels for a system in order to
|
||||
* dynamically determine the current LCN and minimize false triggers from
|
||||
* bogus decoded LTR messages. Tracks the number of occurances of each
|
||||
* LCN and uses a dynamic threshold to determine LCN validity.
|
||||
*/
|
||||
public class LCNTracker
|
||||
{
|
||||
private static final int DEFAULT_COUNT = 10;
|
||||
private int[] mCallLCNCounts;
|
||||
private int[] mFreeLCNCounts;
|
||||
private int mCallHighestCount;
|
||||
private int mFreeHighestCount;
|
||||
private int mCurrentLCN;
|
||||
|
||||
public LCNTracker()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
public void logStatistics()
|
||||
{
|
||||
for(int x = 1; x <= 20; x++)
|
||||
{
|
||||
mLog.debug("Call " + x + ": " + mCallLCNCounts[x]);
|
||||
}
|
||||
mLog.debug("Call Highest Count: " + mCallHighestCount);
|
||||
for(int x = 1; x <= 20; x++)
|
||||
{
|
||||
mLog.debug("Free " + x + ": " + mFreeLCNCounts[x]);
|
||||
}
|
||||
mLog.debug("Free Highest Count: " + mFreeHighestCount);
|
||||
|
||||
mLog.debug("Current LCN: " + mCurrentLCN);
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
//Dim channel arrays to 21 -- ignore the 0 index
|
||||
mCallLCNCounts = new int[21];
|
||||
mFreeLCNCounts = new int[21];
|
||||
mCallHighestCount = 3;
|
||||
mFreeHighestCount = DEFAULT_COUNT;
|
||||
mCurrentLCN = 0;
|
||||
}
|
||||
|
||||
public boolean isCurrentChannel(int channel)
|
||||
{
|
||||
if(mCurrentLCN == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return channel == mCurrentLCN;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentChannel()
|
||||
{
|
||||
return mCurrentLCN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the channel is valid based on the observed current and
|
||||
* free channels reported by the system. Tracks the count of each
|
||||
* reported free channel the highest free channel count is used as a
|
||||
* threshold where a channel is valid when its count exceeds 20% of the
|
||||
* highest free channel count. A channel is also valid when it is
|
||||
* the currently monitored channel.
|
||||
*/
|
||||
public boolean isValidChannel(int channel)
|
||||
{
|
||||
if(isCurrentChannel(channel))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int count = mFreeLCNCounts[channel];
|
||||
|
||||
int threshold = (int) ((double) mFreeHighestCount * 0.2);
|
||||
|
||||
return count >= threshold;
|
||||
}
|
||||
|
||||
public void processCallChannel(int channel)
|
||||
{
|
||||
if(1 <= channel && channel <= 20)
|
||||
{
|
||||
mCallLCNCounts[channel]++;
|
||||
|
||||
if(mCallLCNCounts[channel] > mCallHighestCount)
|
||||
{
|
||||
mCallHighestCount = mCallLCNCounts[channel];
|
||||
mCurrentLCN = channel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void processFreeChannel(int channel)
|
||||
{
|
||||
if(1 <= channel && channel <= 20)
|
||||
{
|
||||
mFreeLCNCounts[channel]++;
|
||||
|
||||
if(mFreeLCNCounts[channel] > mFreeHighestCount)
|
||||
{
|
||||
mFreeHighestCount = mFreeLCNCounts[channel];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Integer> getActiveLCNs()
|
||||
{
|
||||
List<Integer> active = new ArrayList<>();
|
||||
|
||||
if(mFreeHighestCount > DEFAULT_COUNT)
|
||||
{
|
||||
for(int x = 1; x <= 20; x++)
|
||||
{
|
||||
if(mCurrentLCN != 0 && isCurrentChannel(x))
|
||||
{
|
||||
active.add(x);
|
||||
}
|
||||
else if(isValidChannel(x))
|
||||
{
|
||||
active.add(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return active;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package io.github.dsheirer.module.decode.ltrstandard;
|
||||
|
||||
import io.github.dsheirer.filter.Filter;
|
||||
import io.github.dsheirer.filter.FilterElement;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.MessageType;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.message.LTRStandardMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class LTRStandardMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<MessageType, FilterElement<MessageType>> mElements =
|
||||
new HashMap<MessageType, FilterElement<MessageType>>();
|
||||
|
||||
public LTRStandardMessageFilter()
|
||||
{
|
||||
super( "LTR 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 ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
LTRStandardMessage ltr = (LTRStandardMessage)message;
|
||||
|
||||
if( mElements.containsKey( ltr.getMessageType() ) )
|
||||
{
|
||||
return mElements.get( ltr.getMessageType() ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof LTRStandardMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mElements.values() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.ltrstandard;
|
||||
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.edac.CRC;
|
||||
import io.github.dsheirer.edac.CRCLTR;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.message.CallEndMessage;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.message.CallMessage;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.message.IdleMessage;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.message.LTRStandardMessage;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.message.UnknownMessage;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
public class LTRStandardMessageProcessor implements Listener<BinaryMessage>
|
||||
{
|
||||
private MessageDirection mDirection;
|
||||
private AliasList mAliasList;
|
||||
private Listener<Message> mMessageListener;
|
||||
|
||||
/**
|
||||
* Processes raw binary messages and converts them to the correct message class
|
||||
*
|
||||
* @param direction - inbound (ISW) or outbound (OSW)
|
||||
* @param list - alias list
|
||||
*/
|
||||
public LTRStandardMessageProcessor( MessageDirection direction, AliasList list )
|
||||
{
|
||||
mDirection = direction;
|
||||
mAliasList = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( BinaryMessage binaryMessage )
|
||||
{
|
||||
if( mMessageListener != null )
|
||||
{
|
||||
//Inbound Status Word (ISW) is a bit-flipped version of the Outbound
|
||||
//(OSW), so flip the bits and process it as an OSW
|
||||
if( mDirection == MessageDirection.ISW )
|
||||
{
|
||||
binaryMessage.flip( 0, 40 );
|
||||
}
|
||||
|
||||
CRC crc = CRCLTR.check( binaryMessage, mDirection );
|
||||
|
||||
if( crc != CRC.FAILED_CRC &&
|
||||
crc != CRC.FAILED_PARITY )
|
||||
{
|
||||
LTRStandardMessage message;
|
||||
|
||||
int channel = binaryMessage.getInt( LTRStandardMessage.CHANNEL );
|
||||
int home = binaryMessage.getInt( LTRStandardMessage.HOME_REPEATER );
|
||||
int free = binaryMessage.getInt( LTRStandardMessage.FREE );
|
||||
int group = binaryMessage.getInt( LTRStandardMessage.GROUP );
|
||||
|
||||
if( isValidChannel( channel ) &&
|
||||
isValidChannel( home ) &&
|
||||
isValidChannel( free ) )
|
||||
{
|
||||
if( channel == free && group == 255 )
|
||||
{
|
||||
message = new IdleMessage( binaryMessage, mDirection, mAliasList, crc );
|
||||
}
|
||||
else
|
||||
{
|
||||
message = new CallMessage( binaryMessage, mDirection, mAliasList, crc );
|
||||
}
|
||||
}
|
||||
else if( channel == 31 &&
|
||||
isValidChannel( home ) &&
|
||||
isValidChannel( free ) )
|
||||
{
|
||||
message = new CallEndMessage( binaryMessage, mDirection, mAliasList, crc );
|
||||
}
|
||||
else
|
||||
{
|
||||
message = new UnknownMessage( binaryMessage, mDirection, mAliasList, crc );
|
||||
}
|
||||
|
||||
mMessageListener.receive( message );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the channel (LCN) number to ensure it is in the range 1 -20
|
||||
*/
|
||||
private boolean isValidChannel( int channel )
|
||||
{
|
||||
return ( 1 <= channel && channel <= 20 );
|
||||
}
|
||||
|
||||
public void setMessageListener( Listener<Message> listener )
|
||||
{
|
||||
mMessageListener = listener;
|
||||
}
|
||||
|
||||
public void removeMessageListener()
|
||||
{
|
||||
mMessageListener = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.ltrstandard.message;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.edac.CRC;
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.message.MessageType;
|
||||
|
||||
public class CallEndMessage extends LTRStandardMessage
|
||||
{
|
||||
public CallEndMessage(BinaryMessage message, MessageDirection direction,
|
||||
AliasList list, CRC crc )
|
||||
{
|
||||
super( message, direction, list, crc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageType getMessageType()
|
||||
{
|
||||
return MessageType.CA_ENDD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "END* AREA:" );
|
||||
sb.append( getArea() );
|
||||
sb.append( " LCN:" );
|
||||
sb.append( getChannelFormatted() );
|
||||
sb.append( " TG [" );
|
||||
sb.append( getToID() );
|
||||
sb.append( "/" );
|
||||
Alias endAlias = getToIDAlias();
|
||||
if( endAlias != null )
|
||||
{
|
||||
sb.append( getToIDAlias().getName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "UNKNOWN" );
|
||||
}
|
||||
sb.append( "] FREE:" );
|
||||
sb.append( getFreeFormatted() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.ltrstandard.message;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.edac.CRC;
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.message.MessageType;
|
||||
|
||||
public class CallMessage extends LTRStandardMessage
|
||||
{
|
||||
public CallMessage(BinaryMessage message, MessageDirection direction, AliasList list, CRC crc )
|
||||
{
|
||||
super( message, direction, list, crc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageType getMessageType()
|
||||
{
|
||||
return MessageType.CA_STRT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "CALL LCN:" );
|
||||
sb.append( getChannelFormatted() );
|
||||
sb.append( " TG [ " );
|
||||
sb.append( getToID() );
|
||||
sb.append( "/" );
|
||||
|
||||
Alias alias = getToIDAlias();
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( getToIDAlias().getName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "UNKNOWN" );
|
||||
}
|
||||
|
||||
sb.append( " ] FREE:" );
|
||||
sb.append( getFreeFormatted() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.ltrstandard.message;
|
||||
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.edac.CRC;
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.message.MessageType;
|
||||
|
||||
public class IdleMessage extends LTRStandardMessage
|
||||
{
|
||||
public IdleMessage(BinaryMessage message, MessageDirection direction,
|
||||
AliasList list, CRC crc )
|
||||
{
|
||||
super( message, direction, list, crc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageType getMessageType()
|
||||
{
|
||||
return MessageType.SY_IDLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "IDLE AREA:" );
|
||||
sb.append( getArea() );
|
||||
sb.append( " LCN:" );
|
||||
sb.append( getChannelFormatted() );
|
||||
sb.append( " HOME:" );
|
||||
sb.append( getHomeRepeaterFormatted() );
|
||||
sb.append( " GRP:" );
|
||||
sb.append( getGroupFormatted() );
|
||||
sb.append( " FREE:" );
|
||||
sb.append( getFreeFormatted() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.ltrstandard.message;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.edac.CRC;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.message.MessageType;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class LTRStandardMessage extends Message
|
||||
{
|
||||
protected SimpleDateFormat mDatestampFormatter =
|
||||
new SimpleDateFormat( "yyyyMMdd HHmmss" );
|
||||
|
||||
public static final int[] SYNC = { 0,1,2,3,4,5,6,7,8 };
|
||||
public static final int[] AREA = { 9 };
|
||||
public static final int[] CHANNEL = { 10,11,12,13,14 };
|
||||
public static final int[] HOME_REPEATER = { 15,16,17,18,19 };
|
||||
public static final int[] GROUP = { 20,21,22,23,24,25,26,27 };
|
||||
public static final int[] FREE = { 28,29,30,31,32 };
|
||||
public static final int[] CHECKSUM = { 33,34,35,36,37,38,39 };
|
||||
|
||||
protected BinaryMessage mMessage;
|
||||
protected MessageDirection mMessageDirection;
|
||||
protected AliasList mAliasList;
|
||||
protected CRC mCRC;
|
||||
|
||||
public LTRStandardMessage( BinaryMessage message,
|
||||
MessageDirection direction,
|
||||
AliasList list,
|
||||
CRC crc )
|
||||
{
|
||||
mMessage = message;
|
||||
mMessageDirection = direction;
|
||||
mAliasList = list;
|
||||
mCRC = crc;
|
||||
}
|
||||
|
||||
public abstract MessageType getMessageType();
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
return mCRC != CRC.FAILED_CRC && mCRC != CRC.FAILED_PARITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( mDatestampFormatter.format(
|
||||
new Date( System.currentTimeMillis() ) ) );
|
||||
sb.append( " LTR " );
|
||||
sb.append( mMessageDirection.name() );
|
||||
sb.append( " [" );
|
||||
sb.append( mCRC.getAbbreviation() );
|
||||
sb.append( "] " );
|
||||
sb.append( getMessage() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBinaryMessage()
|
||||
{
|
||||
return mMessage.toString();
|
||||
}
|
||||
|
||||
public CRC getCRC()
|
||||
{
|
||||
return mCRC;
|
||||
}
|
||||
|
||||
public int getArea()
|
||||
{
|
||||
return mMessage.getInt( AREA );
|
||||
}
|
||||
|
||||
public int getChannel()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL );
|
||||
}
|
||||
|
||||
public String getChannelFormatted()
|
||||
{
|
||||
return StringUtils.leftPad( String.valueOf( getChannel() ), 2, "0" );
|
||||
}
|
||||
|
||||
public int getHomeRepeater()
|
||||
{
|
||||
return mMessage.getInt( HOME_REPEATER );
|
||||
}
|
||||
|
||||
public String getHomeRepeaterFormatted()
|
||||
{
|
||||
return StringUtils.leftPad( String.valueOf( getHomeRepeater() ), 2, "0" );
|
||||
}
|
||||
|
||||
public int getGroup()
|
||||
{
|
||||
return mMessage.getInt( GROUP );
|
||||
}
|
||||
|
||||
public String getGroupFormatted()
|
||||
{
|
||||
return StringUtils.leftPad( String.valueOf( getGroup() ), 3, "0" );
|
||||
}
|
||||
|
||||
public int getFree()
|
||||
{
|
||||
return mMessage.getInt( FREE );
|
||||
}
|
||||
|
||||
public String getFreeFormatted()
|
||||
{
|
||||
return StringUtils.leftPad( String.valueOf( getFree() ), 2, "0" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFromID()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToID()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getArea() );
|
||||
sb.append( "-" );
|
||||
sb.append( getHomeRepeaterFormatted() );
|
||||
sb.append( "-" );
|
||||
sb.append( getGroupFormatted() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
return mAliasList.getTalkgroupAlias( getToID() );
|
||||
}
|
||||
|
||||
public List<Alias> getAliases()
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
|
||||
Alias talkgroupAlias = getToIDAlias();
|
||||
|
||||
if( talkgroupAlias != null )
|
||||
{
|
||||
aliases.add( talkgroupAlias );
|
||||
}
|
||||
|
||||
return aliases;
|
||||
}
|
||||
|
||||
public int getCRCChecksum()
|
||||
{
|
||||
return mMessage.getInt( CHECKSUM );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return DecoderType.LTR_STANDARD.getDisplayString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return getMessageType().getDisplayText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorStatus()
|
||||
{
|
||||
return mCRC.getDisplayText();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.ltrstandard.message;
|
||||
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.edac.CRC;
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.message.MessageType;
|
||||
|
||||
public class UnknownMessage extends LTRStandardMessage
|
||||
{
|
||||
public UnknownMessage(BinaryMessage message, MessageDirection direction, AliasList list, CRC crc )
|
||||
{
|
||||
super( message, direction, list, crc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageType getMessageType()
|
||||
{
|
||||
return MessageType.UN_KNWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "UNKNOWN AREA:" );
|
||||
sb.append( getArea() );
|
||||
sb.append( " LCN:" );
|
||||
sb.append( getChannelFormatted() );
|
||||
sb.append( " HOME:" );
|
||||
sb.append( getHomeRepeaterFormatted() );
|
||||
sb.append( " GRP:" );
|
||||
sb.append( getGroupFormatted() );
|
||||
sb.append( " FREE:" );
|
||||
sb.append( getFreeFormatted() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user