Adds event logging, code cleanup and some decoder issue resolution.

This commit is contained in:
denny
2015-09-02 19:41:44 -04:00
parent f4d8ea281d
commit 0f85b7260a
124 changed files with 469 additions and 1416 deletions

View File

@@ -24,10 +24,12 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import message.IMessageListener;
import message.IMessageProvider;
import message.Message;
import module.decode.Decoder;
import module.decode.event.CallEvent;
import module.decode.event.ICallEventListener;
import module.decode.event.ICallEventProvider;
import module.decode.state.DecoderStateEvent;
import module.decode.state.DecoderStateEvent.Event;
@@ -82,7 +84,7 @@ import controller.channel.IChannelEventProvider;
* 5) Invoke the stop() method to stop processing.
*
* Optional: if you want to reuse the processing chain with a new sample source,
* invoke the following method sequence: stop(), reset(), setSource(), start()
* invoke the following method sequence: stop(), setSource(), start()
*/
public class ProcessingChain implements IChannelEventListener
{
@@ -271,11 +273,11 @@ public class ProcessingChain implements IChannelEventListener
{
mModules.add( module );
/* Listeners */
if( module instanceof IMetadataListener )
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Listeners <<<<<<<<<<<<<<<<<<<<<<<<<<< */
if( module instanceof ICallEventListener )
{
mMetadataBroadcaster.addListener(
((IMetadataListener)module).getMetadataListener() );
mCallEventBroadcaster.addListener(
((ICallEventListener)module).getCallEventListener() );
}
if( module instanceof IChannelEventListener )
@@ -295,6 +297,18 @@ public class ProcessingChain implements IChannelEventListener
mDecoderStateEventBroadcaster.addListener(
((IDecoderStateEventListener)module).getDecoderStateListener() );
}
if( module instanceof IMessageListener )
{
mMessageBroadcaster.addListener(
((IMessageListener)module).getMessageListener() );
}
if( module instanceof IMetadataListener )
{
mMetadataBroadcaster.addListener(
((IMetadataListener)module).getMetadataListener() );
}
if( module instanceof IRealBufferListener )
{
@@ -308,13 +322,7 @@ public class ProcessingChain implements IChannelEventListener
((ISquelchStateListener)module).getSquelchStateListener() );
}
/* Providers */
if( module instanceof IMetadataProvider )
{
((IMetadataProvider)module).setMetadataListener(
mMetadataBroadcaster );
}
/* >>>>>>>>>>>>>>>>>>> Providers <<<<<<<<<<<<<<<<<<<<<<<<< */
if( module instanceof IAudioPacketProvider )
{
((IAudioPacketProvider)module).setAudioPacketListener(
@@ -348,6 +356,12 @@ public class ProcessingChain implements IChannelEventListener
((IMessageProvider)module).addMessageListener( mMessageBroadcaster );
}
if( module instanceof IMetadataProvider )
{
((IMetadataProvider)module).setMetadataListener(
mMetadataBroadcaster );
}
if( module instanceof IRealBufferProvider )
{
((IRealBufferProvider)module).setRealBufferListener( mRealBufferBroadcaster );

View File

@@ -1,747 +0,0 @@
/*******************************************************************************
* 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;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import message.Message;
import module.decode.Decoder;
import module.decode.state.ChannelState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import record.Recorder;
import record.wave.ComplexWaveRecorder;
import record.wave.FloatWaveRecorder;
import sample.Broadcaster;
import sample.Listener;
import sample.complex.Complex;
import sample.real.RealBuffer;
import sample.real.RealSampleListener;
import source.ComplexSource;
import source.RealSource;
import source.Source;
import source.config.SourceConfigMixer;
import source.tuner.Tuner;
import source.tuner.TunerChannelSource;
import source.tuner.frequency.AutomaticFrequencyControl_R;
import alias.AliasList;
import controller.ResourceManager;
import controller.ThreadPoolManager.ThreadType;
import controller.channel.Channel;
import controller.channel.Channel.ChannelType;
import eventlog.EventLogType;
import eventlog.EventLogger;
/**
* A channel has all of the pieces needed to wire together a source, decoder,
* event logger and recorder and be started and stopped.
*/
public class ProcessingChainOld implements Listener<Message>
{
private final static Logger mLog = LoggerFactory.getLogger( ProcessingChainOld.class );
protected AtomicBoolean mRunning = new AtomicBoolean();
protected Channel mChannel;
protected Source mSource;
protected Decoder mDecoder;
protected List<Recorder> mRecorders = new ArrayList<Recorder>();
protected ArrayList<EventLogger> mEventLoggers = new ArrayList<EventLogger>();
protected AutomaticFrequencyControl_R mAFC;
protected ChannelState mChannelState;
protected ResourceManager mResourceManager;
private ScheduledFuture<?> mSampleProcessorTask;
private AliasList mAliasList;
private ComplexSampleReceiver mComplexReceiver = new ComplexSampleReceiver();
private LinkedTransferQueue<List<Complex>> mComplexQueue =
new LinkedTransferQueue<List<Complex>>();
private RealSampleReceiver mRealReceiver = new RealSampleReceiver();
private LinkedTransferQueue<RealBuffer> mRealQueue =
new LinkedTransferQueue<RealBuffer>();
protected Broadcaster<Message> mBroadcaster = new Broadcaster<Message>();
public ProcessingChainOld( Channel channel, ResourceManager resourceManager )
{
mChannel = channel;
mResourceManager = resourceManager;
if( mResourceManager != null )
{
mAliasList = mResourceManager.getPlaylistManager()
.getPlayist().getAliasDirectory().getAliasList(
mChannel.getAliasListName() );
}
}
// public IAudioOutput getAudioOutput()
// {
// if( mDecoder != null )
// {
// return mDecoder.getAudioOutput();
// }
//
// return null;
// }
public Listener<List<Complex>> getComplexReceiver()
{
return mComplexReceiver;
}
public Listener<RealBuffer> getRealReceiver()
{
return (Listener<RealBuffer>)mRealReceiver;
}
public String toString()
{
return mChannel.getName();
}
public AliasList getAliasList()
{
return mAliasList;
}
public void dispose()
{
if( mSampleProcessorTask != null )
{
mResourceManager.getThreadPoolManager().cancel( mSampleProcessorTask );
}
if( mChannelState != null )
{
mChannelState.dispose();
}
mChannelState = null;
if( mDecoder != null )
{
mDecoder.dispose();
}
mBroadcaster.dispose();
mEventLoggers.clear();
mRecorders.clear();
mResourceManager = null;
}
public ResourceManager getResourceManager()
{
return mResourceManager;
}
public void start()
{
if( !mRunning.get() && mChannel.getEnabled() )
{
updateSource();
updateDecoder();
updateEventLogging();
updateRecording();
mRunning.set( true );
}
else
{
mLog.info( getLogPrefix() + "start() invoked, but processing chain is "
+ "already started" );
}
}
/**
* Performs closeout operations to prepare for channel deletion
*/
public void stop()
{
if( mRunning.get() )
{
updateSource();
updateDecoder();
updateRecording();
/* Flush call events to the logger */
if( getChannel().getChannelType() == ChannelType.STANDARD )
{
// getChannelState().getCallEventModel().flush();
}
updateEventLogging();
mRunning.set( false );
}
else
{
mLog.info( getLogPrefix() + "stop() invoked, but processing chain was "
+ "already stopped" );
}
}
private String getLogPrefix()
{
return "Channel [" + mChannel.getName() + "] - ";
}
private void releaseSource()
{
if( mSource != null )
{
if( mSource instanceof ComplexSource )
{
// ((ComplexSource)mSource).removeAttributeListener( this.getComplexReceiver() );
}
else if( mSource instanceof RealSource )
{
((RealSource)mSource)
.removeListener( this.getRealReceiver() );
}
if( mSampleProcessorTask != null )
{
mResourceManager.getThreadPoolManager().cancel( mSampleProcessorTask );
}
mSource.dispose();
mSource = null;
}
}
private void obtainSource()
{
if( mSource != null )
{
releaseSource();
}
if( mChannel.getEnabled() && mResourceManager != null )
{
// try
// {
// mSource = mResourceManager.getSourceManager()
// .getSource( ProcessingChainOld.this );
// }
// catch ( SourceException e )
// {
// mLog.error( "Couldn't obtain source for processing chain [" +
// toString() + "]", e );
//
// mSource = null;
// }
if( mSource != null )
{
if( mSource instanceof ComplexSource )
{
try
{
mSampleProcessorTask =
mResourceManager.getThreadPoolManager()
.scheduleFixedRate( ThreadType.DECODER,
new ComplexProcessor(),
50, TimeUnit.MILLISECONDS );
// ((ComplexSource)mSource)
// .setListener( this.getComplexReceiver() );
}
catch( RejectedExecutionException ree )
{
mLog.error( getLogPrefix() + "ProcessingChain - "
+ "error scheduling complex sample processing "
+ "thread - " + ree.getLocalizedMessage() );
mSource.dispose();
}
}
else if( mSource instanceof RealSource )
{
try
{
mSampleProcessorTask =
mResourceManager.getThreadPoolManager()
.scheduleFixedRate( ThreadType.DECODER,
new RealProcessor(),
50, TimeUnit.MILLISECONDS );
((RealSource)mSource)
.setListener( this.getRealReceiver() );
}
catch( RejectedExecutionException ree )
{
mLog.error( getLogPrefix() + "ProcessingChain - "
+ "error scheduling float sample processing "
+ "thread", ree );
mSource.dispose();
}
}
}
}
}
public void updateSource()
{
/* Cleanup existing source */
releaseSource();
/* Get a new source if needed and start the sample processor thread */
obtainSource();
}
public void updateDecoder()
{
if( mChannel.getEnabled() )
{
if( mDecoder != null )
{
mDecoder.init();
}
else
{
// /* Setup the channel state */
// mChannelState = DecoderFactory.getChannelStateNew( this, mAliasList );
if( mSource == null )
{
// mChannelState.setState( State.NO_TUNER );
}
else
{
// mDecoder = DecoderFactory.
// getDecoder( this, mSource.getSampleType(), mAliasList );
if( mDecoder != null )
{
/* Register to receive decoded messages and auxiliary messages */
mDecoder.addMessageListener( ProcessingChainOld.this );
/* Establish two-way communication between the frequency
* correction controller and the tuner channel source */
// if( mSource instanceof TunerChannelSource &&
// mDecoder.hasFrequencyCorrectionControl() )
// {
// TunerChannelSource tcs = (TunerChannelSource)mSource;
//
// FrequencyCorrectionControl fcc =
// mDecoder.getFrequencyCorrectionController();
//
// if( fcc != null )
// {
// tcs.addListener( fcc );
// fcc.setListener( tcs );
// }
}
/* Register audio output to be controlled by the channel state */
// mChannelState.addListener( (SquelchListener)mDecoder.getAudioOutput() );
// mChannelState.setListener( (IAudioTypeListener)mDecoder.getAudioOutput() );
}
}
}
}
// }
/**
* Starts, stops or changes event logging
*/
public void updateEventLogging()
{
/* Shutdown and remove existing event loggers */
if( mEventLoggers != null )
{
for( EventLogger logger: mEventLoggers )
{
logger.stop();
}
mEventLoggers.clear();
}
/* Construct event loggers and add as message listeners */
if( mChannel.getEnabled() &&
mResourceManager != null )
{
//Get the event loggers
ArrayList<EventLogType> types = getChannel()
.getEventLogConfiguration().getLoggers();
for( EventLogType type: types )
{
EventLogger logger;
if( type == EventLogType.CALL_EVENT )
{
logger = mResourceManager.getEventLogManager()
.getLogger( this, type );
// getChannelState().getCallEventModel()
// .addListener( (Listener<CallEvent>)logger );
}
else
{
logger = mResourceManager.getEventLogManager()
.getLogger( this, type );
addListener( (Listener<Message>)logger );
}
logger.start();
mEventLoggers.add( logger );
}
}
}
/**
* Starts, stops or changes data recording
*/
public void updateRecording()
{
/* Remove any existing recorders */
if( mRecorders != null )
{
for( Recorder recorder: mRecorders )
{
if( recorder != null )
{
try
{
recorder.stop();
}
catch ( IOException ioe )
{
mLog.error( getLogPrefix() + "Couldn't stop recorder [" +
recorder.getFileName() + "]", ioe );
}
}
}
}
/* Start any new recorders */
if( mChannel.getEnabled() &&
mResourceManager != null &&
mDecoder != null )
{
mRecorders = mResourceManager.getRecorderManager()
.getRecorder( this );
/* Iterate any returned recorders and start/add them */
for( Recorder recorder: mRecorders )
{
try
{
recorder.start();
if( recorder instanceof FloatWaveRecorder )
{
mLog.info( getLogPrefix() + "- started audio recording [" +
recorder.getFileName() + "]" );
// mDecoder.addRealSampleListener( (FloatWaveRecorder)recorder );
}
else if( recorder instanceof ComplexWaveRecorder )
{
mLog.info( getLogPrefix() + "- started baseband recording [" +
recorder.getFileName() + "]" );
// mDecoder.addComplexListener( (ComplexWaveRecorder )recorder );
}
}
catch ( IOException e )
{
mLog.error( getLogPrefix() + "Unable to start recorder [" +
recorder.getFileName() + "]" );
}
}
}
}
public Channel getChannel()
{
return mChannel;
}
public Source getSource()
{
return mSource;
}
/**
* Returns the tuner that is sourcing this channel, or null if it's being
* sourced from some other source
*/
public Tuner getTuner()
{
Tuner retVal = null;
if( mSource instanceof TunerChannelSource )
{
retVal = ((TunerChannelSource)mSource).getTuner();
}
return retVal;
}
public Decoder getDecoder()
{
return mDecoder;
}
public ChannelState getChannelState()
{
return mChannelState;
}
public boolean isRunning()
{
return mRunning.get();
}
public boolean isProcessing()
{
return isRunning() && mSource != null;
}
private source.mixer.MixerChannel getMixerChannel()
{
source.mixer.MixerChannel retVal = null;
if( mChannel.getSourceConfiguration() instanceof SourceConfigMixer )
{
SourceConfigMixer mixer = (SourceConfigMixer)mChannel.getSourceConfiguration();
retVal = mixer.getChannel();
}
return retVal;
}
@Override
public void receive( Message message )
{
if( message.isValid() )
{
mBroadcaster.receive( message );
}
}
/**
* Adds the listener to receive demodulated samples from the decoder
*/
public void addRealListener( RealSampleListener listener )
{
if( mDecoder != null )
{
// mDecoder.addRealSampleListener( listener );
}
}
/**
* Removes the listener from receiving demodulated samples from the decoder
*/
public void removeRealListener( RealSampleListener listener )
{
if( mDecoder != null )
{
// mDecoder.removeRealSampleListener( listener );
}
}
/**
* Adds a listener to receive a copy of complex (I/Q) baseband samples
* received by this processing chain
*/
public void addComplexListener( Listener<Complex> listener )
{
if( mDecoder != null )
{
// mDecoder.addComplexListener( listener );
}
else
{
mLog.error( getLogPrefix() + "attempt to add a complex sample "
+ "listener, but the decoder is null" );
}
}
/**
* Removes the listener from receiving a copy of complex (I/Q) baseband
* samples received by this processing chain
*/
public void removeComplexListener( Listener<Complex> listener )
{
if( mDecoder != null )
{
// mDecoder.removeComplexListener( listener );
}
else
{
mLog.error( getLogPrefix() + "attempt to remove a complex sample "
+ "listener, but the decoder is null" );
}
}
/**
* Registers the listener to receive messages
*/
public void addListener( Listener<Message> listener )
{
mBroadcaster.addListener( listener );
}
/**
* Registers all listeners in the list to receive messages
*/
public void addListeners( List<Listener<Message>> listeners )
{
for( Listener<Message> listener: listeners )
{
addListener( listener );
}
}
/**
* Removes the listener from receiving messages
*/
public void removeListener( Listener<Message> listener )
{
mBroadcaster.removeListener( listener );
}
/**
* Manages the real sample queue and distributes samples to the decoder.
*/
private class RealProcessor implements Runnable
{
@Override
public void run()
{
try
{
List<RealBuffer> sampleBuffers = new ArrayList<RealBuffer>();
mRealQueue.drainTo( sampleBuffers, 4 );
for( RealBuffer sampleBuffer: sampleBuffers )
{
if( mDecoder != null )
{
float[] samples = sampleBuffer.getSamples();
for( float sample: samples )
{
// mDecoder.getRealReceiver().receive( sample );
}
}
sampleBuffer.dispose();
}
sampleBuffers.clear();
}
catch( Exception e )
{
mLog.error( "error during processing chain real processor run", e );
}
}
}
/**
* Manages the complex sample queue and distributes samples to the decoder.
*/
private class ComplexProcessor implements Runnable
{
@Override
public void run()
{
try
{
List<List<Complex>> sampleSets =
new ArrayList<List<Complex>>();
mComplexQueue.drainTo( sampleSets, 16 );
for( List<Complex> samples: sampleSets )
{
for( Complex sample: samples )
{
if( sample != null && mDecoder != null )
{
// mDecoder.getComplexReceiver().receive( sample );
}
}
samples.clear();
}
sampleSets.clear();
}
catch( Exception e )
{
mLog.error( "error during processing chain complex processor run", e );
}
}
}
/**
* Internal listener to receive complex (I/Q) baseband samples. Places
* received samples into the queue managed by the ComplexProcessor.
*/
public class ComplexSampleReceiver implements Listener<List<Complex>>
{
@Override
public void receive( List<Complex> samples )
{
mComplexQueue.add( samples );
}
}
/**
* Internal listener to receive real(ie demodulated) samples. Places
* received samples into the queue managed by the RealProcessor
*/
public class RealSampleReceiver implements Listener<RealBuffer>
{
@Override
public void receive( RealBuffer samples )
{
mRealQueue.add( samples );
}
}
}

View File

@@ -25,10 +25,8 @@ import javax.swing.JCheckBox;
import javax.swing.SwingUtilities;
import module.decode.config.AuxDecodeConfiguration;
import controller.Editor;
import controller.channel.AbstractChannelEditor;
import controller.channel.ChannelNode;
import controller.channel.ChannelValidationException;
public class AuxDecodeComponentEditor extends AbstractChannelEditor
{

View File

@@ -29,11 +29,9 @@ import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
import module.decode.config.DecodeConfiguration;
import net.miginfocom.swing.MigLayout;
import controller.Editor;
import controller.channel.Channel;
import controller.channel.ChannelValidationException;
public class DecodeEditor extends Editor
{

View File

@@ -258,6 +258,9 @@ public class DecoderFactory
case TAIT_1200:
decoders.add( new Tait1200Decoder( aliasList ) );
break;
default:
throw new IllegalArgumentException( "Unrecognized auxiliary "
+ "decoder type [" + auxDecoder + "]" );
}
}

View File

@@ -21,7 +21,6 @@ import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JButton;
import javax.swing.JFrame;

View File

@@ -0,0 +1,8 @@
package module.decode.event;
import sample.Listener;
public interface ICallEventListener
{
public Listener<CallEvent> getCallEventListener();
}

View File

@@ -19,7 +19,6 @@ package module.decode.fleetsync1;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

View File

@@ -167,6 +167,8 @@ public class FleetsyncCallEvent extends CallEvent
sbDetails.append( message.getStatusAlias().getName() );
}
break;
default:
break;
}
if( type == CallEventType.ID_ANI ||

View File

@@ -85,6 +85,8 @@ public class LJ1200Message extends Message
case PASSED:
mLog.debug( "PASS:" + message.toString() );
break;
default:
break;
}
}

View File

@@ -29,7 +29,6 @@ import alias.Alias;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRC;
import edac.CRCLJ;
public class LJ1200TransponderMessage extends Message
{
@@ -66,6 +65,8 @@ public class LJ1200TransponderMessage extends Message
case UNKNOWN:
mLog.debug( "UNKNOWN:" + message.toString() );
break;
default:
break;
}
}

View File

@@ -160,6 +160,8 @@ public class LTRNetDecoderPanel extends DecoderPanel
mDescription.setForeground( mColorLabelDecoder );
}
break;
default:
break;
}
}
}

View File

@@ -23,7 +23,6 @@ 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;

View File

@@ -21,7 +21,6 @@ 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;

View File

@@ -17,13 +17,12 @@
******************************************************************************/
package module.decode.ltrstandard;
import sample.Listener;
import sample.real.IRealBufferListener;
import sample.real.RealBuffer;
import message.MessageDirection;
import module.decode.Decoder;
import module.decode.DecoderType;
import module.decode.config.DecodeConfiguration;
import sample.Listener;
import sample.real.IRealBufferListener;
import sample.real.RealBuffer;
import alias.AliasList;
import bits.MessageFramer;
import bits.SyncPattern;

View File

@@ -148,6 +148,8 @@ public class MDCCallEvent extends CallEvent
case PAGING:
type = CallEventType.PAGE;
break;
default:
break;
}
return new MDCCallEvent.Builder( type )

View File

@@ -216,6 +216,8 @@ public class MPT1327DecoderPanel extends DecoderPanel
mToTalkgroupLabel.setForeground( mColorLabelDetails );
}
break;
default:
break;
}
}
}

View File

@@ -238,6 +238,8 @@ public class MPT1327DecoderState extends DecoderState
case MAINT:
broadcast( new DecoderStateEvent( this, Event.END, State.END ) );
break;
default:
break;
}
}
}

View File

@@ -581,6 +581,7 @@ public class MPT1327Message extends Message
sb.append( " " );
sb.append( type.getLabel() );
sb.append( " REQUEST" );
break;
}
break;
case ACKI:
@@ -726,8 +727,6 @@ public class MPT1327Message extends Message
sb.append( getChannel() );
sb.append( " SER:" );
sb.append( getAdjacentSiteSerialNumber() );
//debug
sb.append( " *************************" );
break;
case SPECIFY_CALL_MAINTENANCE_PARAMETERS:
sb.append( " PERIODIC MAINT MSG REQD:" );
@@ -738,6 +737,8 @@ public class MPT1327Message extends Message
sb.append( getPresselOnRequired() );
sb.append( " IDENT1 VALUE:" );
sb.append( getMaintMessageIDENT1Value() );
default:
break;
}
break;
case CLEAR:
@@ -777,6 +778,8 @@ public class MPT1327Message extends Message
sb.append( " " );
sb.append( getSDM() );
break;
default:
break;
}
return sb.toString();
@@ -849,6 +852,8 @@ public class MPT1327Message extends Message
sb.append( "SEND SHORT DATA MESSAGE USING " );
sb.append( slots.getLabel() );
break;
default:
break;
}
}
else
@@ -1253,6 +1258,8 @@ public class MPT1327Message extends Message
12 ) );
}
break;
default:
break;
}
return sb.toString();
@@ -1278,6 +1285,8 @@ public class MPT1327Message extends Message
case HEAD_PLUS4:
blocks = 4;
break;
default:
break;
}
if( blocks >= 1 )
@@ -1347,6 +1356,8 @@ public class MPT1327Message extends Message
case HEAD_PLUS4:
blocks = 4;
break;
default:
break;
}
if( blocks >= 1 )
@@ -1446,6 +1457,8 @@ public class MPT1327Message extends Message
case HEAD_PLUS4:
blocks = 4;
break;
default:
break;
}
if( blocks >= 1 )

View File

@@ -17,11 +17,11 @@
******************************************************************************/
package module.decode.mpt1327;
import message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import message.Message;
import module.decode.DecoderFactory;
import sample.Listener;
import alias.AliasList;
import bits.BinaryMessage;

View File

@@ -171,6 +171,8 @@ public class MPT1327TrafficPanel extends DecoderPanel
case CHANNEL_STATE_LABEL_DETAILS:
mToLabel.setForeground( mColorLabelDetails );
break;
default:
break;
}
}
}

View File

@@ -18,6 +18,12 @@ public class C4FMSlicer implements RealSampleListener
private Broadcaster<Dibit> mBroadcaster = new Broadcaster<Dibit>();
public void dispose()
{
mBroadcaster.dispose();
mBroadcaster = null;
}
/**
* Primary method for receiving output from the C4FMSymbolFilter. Slices
* (converts) the filtered sample value into a C4FMSymbol decision.

View File

@@ -229,6 +229,13 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
mFrequencyCorrectionControl.setListener( this );
}
public void dispose()
{
mGainController = null;
mFrequencyCorrectionControl = null;
mListener = null;
}
@Override
public void receive( float sample )
{

View File

@@ -19,6 +19,14 @@ public abstract class P25Decoder extends Decoder
mMessageProcessor = new P25MessageProcessor( aliasList );
mMessageProcessor.setMessageListener( mMessageBroadcaster );
}
public void dispose()
{
super.dispose();
mMessageProcessor.dispose();
mMessageProcessor = null;
}
@Override
public DecoderType getDecoderType()

View File

@@ -21,10 +21,9 @@ import java.awt.EventQueue;
import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;
import module.decode.state.ChangedAttribute;
import module.decode.state.DecoderPanel;
import module.decode.state.State;
import net.miginfocom.swing.MigLayout;
import settings.ColorSetting;
import settings.Setting;
import settings.SettingsManager;
@@ -168,6 +167,8 @@ public class P25DecoderPanel extends DecoderPanel
mToAlias.setIcon( null );
}
break;
default:
break;
}
repaint();

View File

@@ -2264,43 +2264,45 @@ public class P25DecoderState extends DecoderState
{
switch( message.getOpcode() )
{
case GROUP_DATA_CHANNEL_ANNOUNCEMENT:
GroupDataChannelAnnouncement gdca = (GroupDataChannelAnnouncement)message;
broadcast( new P25CallEvent.Builder( CallEventType.ANNOUNCEMENT )
.aliasList( getAliasList() )
.channel( gdca.getChannel1() )
.details( ( gdca.isEncrypted() ? "ENCRYPTED" : "" ) +
( gdca.isEmergency() ? " EMERGENCY" : "") )
.frequency( gdca.getDownlinkFrequency1() )
.to( gdca.getGroupAddress1() )
.build() );
if( gdca.hasChannelNumber2() )
{
case GROUP_DATA_CHANNEL_ANNOUNCEMENT:
GroupDataChannelAnnouncement gdca = (GroupDataChannelAnnouncement)message;
broadcast( new P25CallEvent.Builder( CallEventType.ANNOUNCEMENT )
.aliasList( getAliasList() )
.channel( gdca.getChannel2() )
.channel( gdca.getChannel1() )
.details( ( gdca.isEncrypted() ? "ENCRYPTED" : "" ) +
( gdca.isEmergency() ? " EMERGENCY" : "") )
.frequency( gdca.getDownlinkFrequency2() )
.to( gdca.getGroupAddress2() )
.frequency( gdca.getDownlinkFrequency1() )
.to( gdca.getGroupAddress1() )
.build() );
}
break;
case GROUP_DATA_CHANNEL_ANNOUNCEMENT_EXPLICIT:
GroupDataChannelAnnouncementExplicit gdcae =
(GroupDataChannelAnnouncementExplicit)message;
broadcast( new P25CallEvent.Builder( CallEventType.DATA_CALL )
.aliasList( getAliasList() )
.channel( gdcae.getTransmitChannel() )
.details( ( gdcae.isEncrypted() ? "ENCRYPTED" : "" ) +
( gdcae.isEmergency() ? " EMERGENCY" : "") )
.frequency( gdcae.getDownlinkFrequency() )
.to( gdcae.getGroupAddress() )
.build() );
break;
if( gdca.hasChannelNumber2() )
{
broadcast( new P25CallEvent.Builder( CallEventType.ANNOUNCEMENT )
.aliasList( getAliasList() )
.channel( gdca.getChannel2() )
.details( ( gdca.isEncrypted() ? "ENCRYPTED" : "" ) +
( gdca.isEmergency() ? " EMERGENCY" : "") )
.frequency( gdca.getDownlinkFrequency2() )
.to( gdca.getGroupAddress2() )
.build() );
}
break;
case GROUP_DATA_CHANNEL_ANNOUNCEMENT_EXPLICIT:
GroupDataChannelAnnouncementExplicit gdcae =
(GroupDataChannelAnnouncementExplicit)message;
broadcast( new P25CallEvent.Builder( CallEventType.DATA_CALL )
.aliasList( getAliasList() )
.channel( gdcae.getTransmitChannel() )
.details( ( gdcae.isEncrypted() ? "ENCRYPTED" : "" ) +
( gdcae.isEmergency() ? " EMERGENCY" : "") )
.frequency( gdcae.getDownlinkFrequency() )
.to( gdcae.getGroupAddress() )
.build() );
break;
default:
break;
}
}

View File

@@ -31,7 +31,6 @@ import bits.MultiSyncPatternMatcher;
import bits.SoftSyncDetector;
import bits.SyncDetector;
import dsp.psk.CQPSKDemodulator;
import dsp.psk.CQPSKDemodulator2;
import dsp.symbol.Dibit;
import dsp.symbol.FrameSync;
import edac.BCH_63_16_11;
@@ -47,20 +46,12 @@ public class P25MessageFramer implements Listener<Dibit>
private static final int SYNC_MATCH_THRESHOLD = 2;
private static final int SYNC_IN_CALL_THRESHOLD = 4;
private SoftSyncDetector mPrimarySyncDetector = new SoftSyncDetector(
FrameSync.P25_PHASE1_NORMAL.getSync(), SYNC_MATCH_THRESHOLD );
/* Costas Loop phase lock error correction values. A phase lock error of
* 90 degrees requires a correction of 1/4 of the symbol rate (1200Hz). An
* error of 180 degrees requires a correction of 1/2 of the symbol rate */
public static final double SYMBOL_FREQUENCY = 2.0d * Math.PI * 4800.0d / 48000.0d;
public static final double PHASE_CORRECTION_90_DEGREES = SYMBOL_FREQUENCY / 4.0d;
public static final double PHASE_CORRECTION_180_DEGREES = SYMBOL_FREQUENCY / 2.0d;
private MultiSyncPatternMatcher mMatcher = new MultiSyncPatternMatcher( 48 );
private ArrayList<P25MessageAssembler> mAssemblers =
new ArrayList<P25MessageAssembler>();
public static final int TSBK_BEGIN = 64;
public static final int TSBK_CRC_START = 144;
public static final int TSBK_END = 260;
@@ -77,6 +68,13 @@ public class P25MessageFramer implements Listener<Dibit>
public static final int PDU3_END = 548;
public static final int PDU3_DECODED_END = 448;
private SoftSyncDetector mPrimarySyncDetector = new SoftSyncDetector(
FrameSync.P25_PHASE1_NORMAL.getSync(), SYNC_MATCH_THRESHOLD );
private MultiSyncPatternMatcher mMatcher = new MultiSyncPatternMatcher( 48 );
private ArrayList<P25MessageAssembler> mAssemblers =
new ArrayList<P25MessageAssembler>();
private Listener<Message> mListener;
private AliasList mAliasList;
@@ -143,6 +141,26 @@ public class P25MessageFramer implements Listener<Dibit>
}
}
public void dispose()
{
for( P25MessageAssembler a: mAssemblers )
{
a.dispose();
}
mAssemblers.clear();
mListener = null;
mAliasList = null;
mMatcher.dispose();
mMatcher = null;
mPrimarySyncDetector.dispose();
mPrimarySyncDetector = null;
}
private void dispatch( Message message )
{
if( mListener != null )

View File

@@ -10,7 +10,6 @@ import module.decode.p25.message.ldu.LDUMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.Broadcaster;
import sample.Listener;
import alias.AliasList;

View File

@@ -110,6 +110,33 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
/* Process and broadcast messages */
mMessageFramer.setListener( getMessageProcessor() );
}
@Override
public void dispose()
{
super.dispose();
mC4FMPreFilter.dispose();
mC4FMPreFilter = null;
mDGC.dispose();
mDGC = null;
mStreamConverter.dispose();
mStreamConverter = null;
mFrequencyCorrectionControl.dispose();
mFrequencyCorrectionControl = null;
mSymbolFilter.dispose();
mSymbolFilter = null;
mMessageFramer.dispose();
mMessageFramer = null;
mC4FMSlicer.dispose();
mC4FMSlicer = null;
}
public Modulation getModulation()
{

View File

@@ -21,7 +21,6 @@ import instrument.tap.Tap;
import instrument.tap.stream.ComplexSampleTap;
import instrument.tap.stream.ComplexTap;
import instrument.tap.stream.DibitTap;
import instrument.tap.stream.FloatTap;
import instrument.tap.stream.QPSKTap;
import java.util.ArrayList;
@@ -30,13 +29,13 @@ import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import controller.channel.Channel.ChannelType;
import sample.Listener;
import sample.complex.ComplexBuffer;
import sample.complex.ComplexBufferToStreamConverter;
import sample.complex.IComplexBufferListener;
import source.tuner.frequency.FrequencyCorrectionControl;
import alias.AliasList;
import controller.channel.Channel.ChannelType;
import dsp.filter.FilterFactory;
import dsp.filter.Window.WindowType;
import dsp.filter.fir.complex.ComplexFIRFilter_CB_CB;
@@ -88,6 +87,29 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
mMessageFramer.setListener( getMessageProcessor() );
}
public void dispose()
{
super.dispose();
mBasebandFilter.dispose();
mBasebandFilter = null;
mStreamConverter.dispose();
mStreamConverter = null;
mAGC.dispose();
mAGC = null;
mCQPSKDemodulator.dispose();
mCQPSKDemodulator = null;
mCQPSKSlicer.dispose();
mCQPSKSlicer = null;
mMessageFramer.dispose();
mMessageFramer = null;
}
@Override
public Listener<ComplexBuffer> getComplexBufferListener()
{

View File

@@ -67,35 +67,35 @@ public class Trellis_1_2_Rate
mConstellationNodes.clear();
}
private String constellationsToString( String label )
{
StringBuilder sb = new StringBuilder();
sb.append( label );
for( ConstellationNode node: mConstellationNodes )
{
sb.append( " " + node.getConstellation().name() );
}
return sb.toString();
}
private String inputsToString()
{
StringBuilder sb = new StringBuilder();
sb.append( " INPUTS: " );
for( ConstellationNode node: mConstellationNodes )
{
sb.append( " " );
sb.append( ( node.getConstellation().getInput().getBit1() ? "1" : "0" ) );
sb.append( ( node.getConstellation().getInput().getBit2() ? "1" : "0" ) );
}
return sb.toString();
}
// private String constellationsToString( String label )
// {
// StringBuilder sb = new StringBuilder();
//
// sb.append( label );
//
// for( ConstellationNode node: mConstellationNodes )
// {
// sb.append( " " + node.getConstellation().name() );
// }
//
// return sb.toString();
// }
//
// private String inputsToString()
// {
// StringBuilder sb = new StringBuilder();
//
// sb.append( " INPUTS: " );
//
// for( ConstellationNode node: mConstellationNodes )
// {
// sb.append( " " );
// sb.append( ( node.getConstellation().getInput().getBit1() ? "1" : "0" ) );
// sb.append( ( node.getConstellation().getInput().getBit2() ? "1" : "0" ) );
// }
//
// return sb.toString();
// }
public boolean decode( BinaryMessage message, int start, int end )
{

View File

@@ -5,7 +5,6 @@ import java.util.List;
import message.Message;
import module.decode.p25.message.hdu.HDUMessage;
import module.decode.p25.message.tdu.lc.TDULinkControlMessage;
import filter.Filter;
import filter.FilterElement;

View File

@@ -4,7 +4,6 @@ import java.util.Collections;
import java.util.List;
import message.Message;
import module.decode.p25.message.tdu.TDUMessage;
import module.decode.p25.message.tdu.lc.TDULinkControlMessage;
import filter.Filter;
import filter.FilterElement;

View File

@@ -2,8 +2,6 @@ package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.P25Message.DuplexMode;
import module.decode.p25.message.P25Message.SessionMode;
import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode;

View File

@@ -1,7 +1,5 @@
package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.P25Message.DuplexMode;
import module.decode.p25.message.P25Message.SessionMode;
import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode;

View File

@@ -1,7 +1,5 @@
package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.P25Message.DuplexMode;
import module.decode.p25.message.P25Message.SessionMode;
import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode;

View File

@@ -1,7 +1,5 @@
package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.P25Message.DuplexMode;
import module.decode.p25.message.P25Message.SessionMode;
import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode;

View File

@@ -3,7 +3,6 @@ package module.decode.p25.message.pdu;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;

View File

@@ -1,20 +1,10 @@
package module.decode.p25.message.pdu.confirmed;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.MDPConfigurationOption;
import module.decode.p25.reference.PDUType;
import module.decode.p25.reference.SNDCPActivationRejectReason;
import module.decode.p25.reference.Vendor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRC;
import edac.CRCP25;
public class SNDCPActivateTDSContextAccept extends PDUConfirmedMessage
{
public final static Logger mLog =

View File

@@ -1,7 +1,6 @@
package module.decode.p25.message.pdu.confirmed;
import module.decode.p25.reference.PDUType;
import module.decode.p25.reference.SNDCPActivationRejectReason;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@@ -1,7 +1,5 @@
package module.decode.p25.message.pdu.osp.data;
import java.util.Date;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage;

View File

@@ -2,7 +2,6 @@ package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode;
import module.decode.p25.reference.Service;

View File

@@ -1,6 +1,5 @@
package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger;

View File

@@ -2,8 +2,6 @@ package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.P25Message.DuplexMode;
import module.decode.p25.message.P25Message.SessionMode;
import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger;

View File

@@ -3,7 +3,6 @@ package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.LinkControlOpcode;
import module.decode.p25.reference.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@@ -149,22 +149,22 @@ public abstract class GroupMultiChannelGrant extends ChannelGrant
public long getDownlinkFrequency1()
{
return calculateDownlink( mIdentifierUpdate1, getChannelNumber() );
return calculateDownlink( mIdentifierUpdate1, getChannelNumber1() );
}
public long getUplinkFrequency1()
{
return calculateUplink( mIdentifierUpdate1, getChannelNumber() );
return calculateUplink( mIdentifierUpdate1, getChannelNumber1() );
}
public long getDownlinkFrequency2()
{
return calculateDownlink( mIdentifierUpdate2, getChannelNumber() );
return calculateDownlink( mIdentifierUpdate2, getChannelNumber2() );
}
public long getUplinkFrequency2()
{
return calculateUplink( mIdentifierUpdate2, getChannelNumber() );
return calculateUplink( mIdentifierUpdate2, getChannelNumber2() );
}
}

View File

@@ -1,6 +1,5 @@
package module.decode.p25.message.tsbk.motorola;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import alias.AliasList;
import bits.BinaryMessage;

View File

@@ -3,7 +3,6 @@ package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.Response;
import module.decode.p25.reference.StackOperation;
import alias.AliasList;
import bits.BinaryMessage;

View File

@@ -3,7 +3,6 @@ package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.Response;
import alias.AliasList;
import bits.BinaryMessage;

View File

@@ -1,7 +1,6 @@
package module.decode.p25.message.tsbk.osp.voice;
import module.decode.p25.message.tsbk.UnitChannelGrant;
import module.decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;

View File

@@ -27,7 +27,6 @@ import settings.ColorSetting;
import settings.Setting;
import settings.SettingsManager;
import alias.Alias;
import controller.channel.Channel;
public class PassportDecoderPanel extends DecoderPanel
{

View File

@@ -320,7 +320,7 @@ public class PassportDecoderState extends DecoderState
}
else
{
ArrayList<Integer> channels = new ArrayList( mSiteLCNs.keySet() );
ArrayList<Integer> channels = new ArrayList<>( mSiteLCNs.keySet() );
Collections.sort( channels );
for( Integer channel: channels )
@@ -339,7 +339,7 @@ public class PassportDecoderState extends DecoderState
}
else
{
ArrayList<Integer> channels = new ArrayList( mNeighborLCNs.keySet() );
ArrayList<Integer> channels = new ArrayList<>( mNeighborLCNs.keySet() );
Collections.sort( channels );
for( Integer channel: channels )

View File

@@ -285,17 +285,6 @@ public class PassportMessage extends Message
return mMessage.toString();
}
/**
* Returns a value formatted in hex notation.
*
* @param value - integer value
* @return - hex digits returned
*/
private static String getHex( int value, int digits )
{
return String.format( "%0" + digits + "X", value );
}
private int getInt( int[] bits )
{
int retVal = 0;

View File

@@ -17,13 +17,12 @@
******************************************************************************/
package module.decode.state;
import message.Message;
import module.decode.state.DecoderStateEvent.Event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import message.Message;
import module.ProcessingChain;
import module.decode.state.DecoderStateEvent.Event;
/**
* Basic decoder channel state - provides the minimum channel state functionality
* to support an always un-squelched audio decoder.

View File

@@ -156,11 +156,6 @@ public class Tait1200ANIMessage extends Message
return (char)value;
}
private void checkCRC()
{
// mCRC = CRCLJ.checkAndCorrect( mMessage );
}
public boolean isValid()
{
// return mCRC == CRC.PASSED || mCRC == CRC.CORRECTED;

View File

@@ -0,0 +1,63 @@
/*******************************************************************************
* 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.log;
import java.nio.file.Path;
import module.decode.event.CallEvent;
import module.decode.event.ICallEventListener;
import sample.Listener;
public class CallEventLogger extends EventLogger implements ICallEventListener,
Listener<CallEvent>
{
public CallEventLogger( Path logDirectory, String fileNameSuffix )
{
super( logDirectory, fileNameSuffix );
}
@Override
public void receive( CallEvent callEvent )
{
write( callEvent.toCSV() );
}
@Override
public String getHeader()
{
return CallEvent.getCSVHeader();
}
@Override
public Listener<CallEvent> getCallEventListener()
{
return this;
}
@Override
public void dispose()
{
super.stop();
}
@Override
public void init()
{
super.start();
}
}

View File

@@ -0,0 +1,97 @@
/*******************************************************************************
* 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.log;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.SwingUtilities;
import module.log.config.EventLogConfiguration;
import controller.channel.AbstractChannelEditor;
import controller.channel.ChannelNode;
public class EventLogComponentEditor extends AbstractChannelEditor
{
private static final long serialVersionUID = 1L;
private JCheckBox mBinaryLogger = new JCheckBox( "Binary Messages" );
private JCheckBox mDecodedLogger = new JCheckBox( "Decoded Messages" );
private JCheckBox mCallEventLogger = new JCheckBox( "Call Events" );
public EventLogComponentEditor( ChannelNode channelNode )
{
super( channelNode );
add( mBinaryLogger, "span" );
add( mDecodedLogger, "span" );
add( mCallEventLogger, "span" );
reset();
}
/**
* Sets the combo box to the type stored in the config object, causing the
* editor panel to reset with the stored config
*/
public void reset()
{
SwingUtilities.invokeLater(new Runnable()
{
final List<EventLogType> mLoggers = mChannelNode.getChannel()
.getEventLogConfiguration().getLoggers();
@Override
public void run()
{
mBinaryLogger.setSelected(
mLoggers.contains( EventLogType.BINARY_MESSAGE ) );
mDecodedLogger.setSelected(
mLoggers.contains( EventLogType.DECODED_MESSAGE ) );
mCallEventLogger.setSelected(
mLoggers.contains( EventLogType.CALL_EVENT ) );
}
});
}
/**
* Saves the current configuration as the stored configuration
*/
@Override
public void save()
{
EventLogConfiguration config = mChannelNode.getChannel()
.getEventLogConfiguration();
config.clear();
if( mBinaryLogger.isSelected() )
{
config.addLogger( EventLogType.BINARY_MESSAGE );
}
if( mDecodedLogger.isSelected() )
{
config.addLogger( EventLogType.DECODED_MESSAGE );
}
if( mCallEventLogger.isSelected() )
{
config.addLogger( EventLogType.CALL_EVENT );
}
}
}

View File

@@ -0,0 +1,71 @@
/*******************************************************************************
* 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.log;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import module.Module;
import module.log.MessageEventLogger.Type;
import module.log.config.EventLogConfiguration;
import properties.SystemProperties;
public class EventLogManager
{
private Path mDirectory;
public EventLogManager()
{
mDirectory = SystemProperties.getInstance()
.getApplicationFolder( "event_logs" );
}
public List<Module> getLoggers( EventLogConfiguration config, String prefix )
{
List<Module> loggers = new ArrayList<Module>();
for( EventLogType type: config.getLoggers() )
{
loggers.add( getLogger( type, prefix ) );
}
return loggers;
}
public EventLogger getLogger( EventLogType eventLogType, String prefix )
{
StringBuilder sb = new StringBuilder();
sb.append( prefix );
sb.append( eventLogType.getFileSuffix() );
sb.append( ".log" );
switch( eventLogType )
{
case BINARY_MESSAGE:
return new MessageEventLogger( mDirectory, sb.toString(), Type.BINARY );
case DECODED_MESSAGE:
return new MessageEventLogger( mDirectory, sb.toString(), Type.DECODED );
case CALL_EVENT:
return new CallEventLogger( mDirectory, sb.toString() );
default:
return null;
}
}
}

View File

@@ -0,0 +1,51 @@
/*******************************************************************************
* 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.log;
public enum EventLogType
{
BINARY_MESSAGE( "Binary Messages", "_binary_messages" ),
DECODED_MESSAGE( "Decoded Messages", "_decoded_messages" ),
CALL_EVENT( "Call Events", "_call_events" );
private String mDisplayString;
private String mFileSuffix;
EventLogType( String displayString, String fileSuffix )
{
mDisplayString = displayString;
mFileSuffix = fileSuffix;
}
public String getDisplayString()
{
return mDisplayString;
}
public String getFileSuffix()
{
return mFileSuffix;
}
@Override
public String toString()
{
return mDisplayString;
}
}

View File

@@ -0,0 +1,139 @@
/*******************************************************************************
* 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.log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.file.Path;
import module.Module;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.TimeStamp;
public abstract class EventLogger extends Module
{
private final static Logger mLog =
LoggerFactory.getLogger( EventLogger.class );
/* Illegal filename characters */
private static final String[] mIllegalCharacters =
{ "#", "%", "&", "{", "}", "\\", "<", ">", "*", "?", "/",
" ", "$", "!", "'", "\"", ":", "@", "+", "`", "|", "=" };
private Path mLogDirectory;
private String mFileNameSuffix;
private String mLogFileName;
protected Writer mLogFile;
public EventLogger( Path logDirectory, String fileNameSuffix )
{
mLogDirectory = logDirectory;
mFileNameSuffix = fileNameSuffix;
}
public String toString()
{
if( mLogFileName != null )
{
return mLogFileName;
}
else
{
return "Unknown";
}
}
public abstract String getHeader();
public void start()
{
if( mLogFile == null )
{
try
{
StringBuilder sb = new StringBuilder();
sb.append( mLogDirectory );
sb.append( File.separator );
sb.append( TimeStamp.getTimeStamp( "_" ) );
sb.append( "_" );
sb.append( replaceIllegalCharacters( mFileNameSuffix ) );
mLogFileName = sb.toString();
mLog.info( "Creating log file:" + mLogFileName );
mLogFile = new OutputStreamWriter(new FileOutputStream( mLogFileName ) );
write( getHeader() );
}
catch (FileNotFoundException e)
{
mLog.error("Couldn't create log file in directory:" + mLogDirectory );
}
}
}
/**
* Replaces any illegal filename characters in the proposed filename
*/
private String replaceIllegalCharacters( String filename )
{
for( String illegalCharacter: mIllegalCharacters )
{
filename = filename.replace( illegalCharacter, "_" );
}
return filename;
}
public void stop()
{
if( mLogFile != null )
{
try
{
mLogFile.flush();
mLogFile.close();
mLogFile = null;
}
catch( Exception e )
{
mLog.error( "Couldn't close log file:" + mFileNameSuffix );
}
}
}
protected void write( String eventLogEntry )
{
try
{
mLogFile.write( eventLogEntry + "\n" );
}
catch ( IOException e )
{
mLog.error( "Error writing entry to event log file", e );
}
}
}

View File

@@ -0,0 +1,89 @@
/*******************************************************************************
* 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.log;
import java.nio.file.Path;
import message.IMessageListener;
import message.Message;
import sample.Listener;
import util.TimeStamp;
public class MessageEventLogger extends EventLogger implements
IMessageListener, Listener<Message>
{
public enum Type
{
BINARY, DECODED
};
private Type mType;
public MessageEventLogger( Path logDirectory,
String fileNameSuffix,
Type type )
{
super( logDirectory, fileNameSuffix );
mType = type;
}
@Override
public Listener<Message> getMessageListener()
{
return this;
}
@Override
public void dispose()
{
super.stop();
}
@Override
public void init()
{
super.start();
}
@Override
public void receive( Message message )
{
StringBuilder sb = new StringBuilder();
sb.append( TimeStamp.getTimeStamp( " " ) );
sb.append( "," );
sb.append( ( message.isValid() ? "PASSED" : "FAILED" ) );
sb.append( "," );
if ( mType == Type.BINARY )
{
sb.append( message.getBinaryMessage() );
} else
{
sb.append( message.getMessage() );
}
write( sb.toString() );
}
@Override
public String getHeader()
{
return mType.toString() + " Message Logger\n";
}
}

View File

@@ -0,0 +1,58 @@
/*******************************************************************************
* 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.log.config;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import module.log.EventLogType;
import controller.config.Configuration;
@XmlRootElement( name = "event_log_configuration" )
public class EventLogConfiguration extends Configuration
{
protected List<EventLogType> mLoggers = new ArrayList<EventLogType>();
public EventLogConfiguration()
{
}
@XmlElement( name = "logger" )
public List<EventLogType> getLoggers()
{
return mLoggers;
}
public void setLoggers( ArrayList<EventLogType> loggers )
{
mLoggers = loggers;
}
public void addLogger( EventLogType logger )
{
mLoggers.add( logger );
}
public void clear()
{
mLoggers.clear();
}
}