mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 09:37:36 -05:00
Initial code check in continued
This commit is contained in:
171
src/decode/mpt1327/MPT1327ActivitySummary.java
Normal file
171
src/decode/mpt1327/MPT1327ActivitySummary.java
Normal file
@@ -0,0 +1,171 @@
|
||||
/*******************************************************************************
|
||||
* 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 decode.mpt1327;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import message.Message;
|
||||
import sample.Listener;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import controller.activity.ActivitySummaryProvider;
|
||||
|
||||
public class MPT1327ActivitySummary implements ActivitySummaryProvider,
|
||||
Listener<Message>
|
||||
{
|
||||
private static final int sINT_NULL_VALUE = -1;
|
||||
|
||||
private AliasList mAliasList;
|
||||
private TreeSet<String> mIdents = new TreeSet<String>();
|
||||
private int mSite;
|
||||
|
||||
/**
|
||||
* Compiles a summary of active talkgroups, unique radio ids encountered
|
||||
* in the decoded messages. Talkgroups have to be heard a minimum of twice
|
||||
* to be considered valid ... in order to weed out the invalid ones.
|
||||
*
|
||||
* Returns a textual summary of the activity
|
||||
*/
|
||||
public MPT1327ActivitySummary( AliasList list )
|
||||
{
|
||||
mAliasList = list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup method
|
||||
*/
|
||||
public void dispose()
|
||||
{
|
||||
mIdents.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
{
|
||||
if( message instanceof MPT1327Message )
|
||||
{
|
||||
MPT1327Message mpt = ((MPT1327Message)message);
|
||||
|
||||
if( mpt.isValid() )
|
||||
{
|
||||
switch( mpt.getMessageType() )
|
||||
{
|
||||
case ACK:
|
||||
mIdents.add( mpt.getFromID() );
|
||||
break;
|
||||
case ACKI:
|
||||
mIdents.add( mpt.getFromID() );
|
||||
mIdents.add( mpt.getToID() );
|
||||
break;
|
||||
case ALH:
|
||||
mSite = mpt.getSiteID();
|
||||
break;
|
||||
case GTC:
|
||||
if( mpt.hasFromID() )
|
||||
{
|
||||
mIdents.add( mpt.getFromID() );
|
||||
}
|
||||
if( mpt.hasToID() )
|
||||
{
|
||||
mIdents.add( mpt.getToID() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummary()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "Activity Summary\n" );
|
||||
sb.append( "Decoder:\tMPT-1327\n" );
|
||||
sb.append( "Site:\t" );
|
||||
|
||||
if( mSite != 0 )
|
||||
{
|
||||
sb.append( mSite );
|
||||
|
||||
if( mAliasList != null )
|
||||
{
|
||||
Alias siteAlias = mAliasList.getSiteID( mSite );
|
||||
|
||||
if( siteAlias != null )
|
||||
{
|
||||
sb.append( " " );
|
||||
sb.append( siteAlias.getName() );
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "Network:\t" );
|
||||
|
||||
if( ( mSite & 0x4000 ) == 0x4000 )
|
||||
{
|
||||
sb.append( "National #" );
|
||||
int net = (int)Long.rotateRight( ( mSite & 0x3000 ) , 12 );
|
||||
sb.append( net );
|
||||
sb.append( "\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "Regional\n" );
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "Unknown\n" );
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
|
||||
sb.append( "Talkgroups\n" );
|
||||
if( mIdents.isEmpty() )
|
||||
{
|
||||
sb.append( " None\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator<String> it = mIdents.iterator();
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
String ident = it.next();
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( ident );
|
||||
sb.append( " " );
|
||||
|
||||
Alias alias = mAliasList.getMPT1327Alias( ident );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( alias.getName() );
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
154
src/decode/mpt1327/MPT1327CallEvent.java
Normal file
154
src/decode/mpt1327/MPT1327CallEvent.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*******************************************************************************
|
||||
* 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 decode.mpt1327;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import controller.activity.CallEvent;
|
||||
import decode.DecoderType;
|
||||
|
||||
public class MPT1327CallEvent extends CallEvent
|
||||
{
|
||||
private int mChannel;
|
||||
private int mFrequency;
|
||||
|
||||
public MPT1327CallEvent( CallEventType callEventType,
|
||||
AliasList aliasList,
|
||||
String fromID,
|
||||
String toID,
|
||||
int channel,
|
||||
int frequency,
|
||||
String details )
|
||||
{
|
||||
super( DecoderType.MPT1327, callEventType,
|
||||
aliasList, fromID, toID, details );
|
||||
|
||||
mChannel = channel;
|
||||
mFrequency = frequency;
|
||||
}
|
||||
|
||||
private Alias getAlias( String mpt1327Talkgroup )
|
||||
{
|
||||
if( hasAliasList() )
|
||||
{
|
||||
return getAliasList().getMPT1327Alias( mpt1327Talkgroup );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
return getAlias( getFromID() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
return getAlias( getToID() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChannel()
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrequency()
|
||||
{
|
||||
return mFrequency;
|
||||
}
|
||||
|
||||
public static class Builder
|
||||
{
|
||||
/* Required parameters */
|
||||
private CallEventType mCallEventType;
|
||||
|
||||
/* Optional parameters */
|
||||
private AliasList mAliasList;
|
||||
private String mFromID;
|
||||
private String mToID;
|
||||
private String mDetails;
|
||||
private int mChannel;
|
||||
private int mFrequency;
|
||||
|
||||
public Builder( CallEventType callEventType )
|
||||
{
|
||||
mCallEventType = callEventType;
|
||||
}
|
||||
|
||||
public Builder aliasList( AliasList aliasList )
|
||||
{
|
||||
mAliasList = aliasList;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder from( String val )
|
||||
{
|
||||
mFromID = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder channel( int channel )
|
||||
{
|
||||
mChannel = channel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder details( String details )
|
||||
{
|
||||
mDetails = details;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder frequency( int frequency )
|
||||
{
|
||||
mFrequency = frequency;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder to( String toID )
|
||||
{
|
||||
mToID = toID;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MPT1327CallEvent build()
|
||||
{
|
||||
return new MPT1327CallEvent( this );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor for the builder
|
||||
*/
|
||||
private MPT1327CallEvent( Builder builder )
|
||||
{
|
||||
this( builder.mCallEventType,
|
||||
builder.mAliasList,
|
||||
builder.mFromID,
|
||||
builder.mToID,
|
||||
builder.mChannel,
|
||||
builder.mFrequency,
|
||||
builder.mDetails );
|
||||
}
|
||||
|
||||
}
|
||||
346
src/decode/mpt1327/MPT1327ChannelState.java
Normal file
346
src/decode/mpt1327/MPT1327ChannelState.java
Normal file
@@ -0,0 +1,346 @@
|
||||
/*******************************************************************************
|
||||
* 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 decode.mpt1327;
|
||||
|
||||
import message.Message;
|
||||
import sample.Listener;
|
||||
import source.config.SourceConfigTuner;
|
||||
import alias.AliasList;
|
||||
import audio.SquelchListener;
|
||||
import audio.SquelchListener.SquelchState;
|
||||
import controller.activity.CallEvent.CallEventType;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import controller.channel.ChannelMap;
|
||||
import controller.channel.ProcessingChain;
|
||||
import controller.state.AuxChannelState;
|
||||
import controller.state.ChannelState;
|
||||
import decode.config.DecodeConfigMPT1327;
|
||||
|
||||
public class MPT1327ChannelState extends ChannelState
|
||||
{
|
||||
private int mSite;
|
||||
private String mFromTalkgroup;
|
||||
private String mToTalkgroup;
|
||||
private int mChannelNumber;
|
||||
private ChannelType mChannelType;
|
||||
private ChannelMap mChannelMap;
|
||||
private MPT1327ActivitySummary mActivitySummary;
|
||||
|
||||
public MPT1327ChannelState( ProcessingChain processingChain,
|
||||
AliasList aliasList,
|
||||
ChannelMap channelMap )
|
||||
{
|
||||
super( processingChain, aliasList );
|
||||
|
||||
mActivitySummary = new MPT1327ActivitySummary( aliasList );
|
||||
|
||||
mChannelMap = channelMap;
|
||||
|
||||
mChannelType = processingChain.getChannel().getChannelType();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
|
||||
mActivitySummary.dispose();
|
||||
mActivitySummary = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActivitySummary()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mActivitySummary.getSummary() );
|
||||
|
||||
for( AuxChannelState state: mAuxChannelStates )
|
||||
{
|
||||
sb.append( state.getActivitySummary() );
|
||||
sb.append( "\n\n" );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
{
|
||||
super.receive( message );
|
||||
|
||||
if( message instanceof MPT1327Message )
|
||||
{
|
||||
mActivitySummary.receive( message );
|
||||
|
||||
MPT1327Message mpt = (MPT1327Message)message;
|
||||
|
||||
if( mpt.isValid() )
|
||||
{
|
||||
switch( mpt.getMessageType() )
|
||||
{
|
||||
case AHYC:
|
||||
mCallEventModel.add(
|
||||
new MPT1327CallEvent.Builder( CallEventType.SDM )
|
||||
.aliasList( getProcessingChain().getAliasList() )
|
||||
.channel( mChannelNumber )
|
||||
.details( "Short Data Message" )
|
||||
.frequency( mChannelMap.getFrequency( mChannelNumber ) )
|
||||
.from( mpt.getFromID() )
|
||||
.to( mpt.getToID() )
|
||||
.build() );
|
||||
break;
|
||||
case AHYQ:
|
||||
mCallEventModel.add(
|
||||
new MPT1327CallEvent.Builder( CallEventType.STATUS )
|
||||
.aliasList( getProcessingChain().getAliasList() )
|
||||
.channel( mChannelNumber )
|
||||
.details( mpt.getStatusMessage() )
|
||||
.frequency( mChannelMap.getFrequency( mChannelNumber ) )
|
||||
.from( mpt.getFromID() )
|
||||
.to( mpt.getToID() )
|
||||
.build() );
|
||||
break;
|
||||
case ALH:
|
||||
int sys = mpt.getSiteID();
|
||||
|
||||
if( sys != 0 && sys != mSite )
|
||||
{
|
||||
mSite = sys;
|
||||
broadcastChange( ChangedAttribute.CHANNEL_SITE_NUMBER );
|
||||
}
|
||||
setState( State.CONTROL );
|
||||
break;
|
||||
case GTC:
|
||||
int channelNumber = mpt.getChannel();
|
||||
|
||||
if( !getProcessingChain().getChannel()
|
||||
.hasTrafficChannel( channelNumber ) )
|
||||
{
|
||||
String aliasListName = mProcessingChain
|
||||
.getChannel().getAliasListName();
|
||||
|
||||
Channel traffic = getTrafficChannel( channelNumber,
|
||||
aliasListName );
|
||||
|
||||
/* Set the system and site to same as control channel */
|
||||
traffic.setSystem( getProcessingChain().getChannel()
|
||||
.getSystem(), false );
|
||||
traffic.setSite( getProcessingChain().getChannel()
|
||||
.getSite(), false );
|
||||
|
||||
/* Add the traffic channel to the parent control channel */
|
||||
getProcessingChain().getChannel()
|
||||
.addTrafficChannel( channelNumber, traffic );
|
||||
|
||||
/* Start the traffic channel */
|
||||
traffic.setEnabled( true );
|
||||
|
||||
/* Set traffic channel state info */
|
||||
MPT1327ChannelState trafficState =
|
||||
(MPT1327ChannelState)traffic
|
||||
.getProcessingChain().getChannelState();
|
||||
|
||||
MPT1327ChannelState controlState =
|
||||
(MPT1327ChannelState)getProcessingChain()
|
||||
.getChannelState();
|
||||
|
||||
trafficState.setChannelMap( controlState.getChannelMap() );
|
||||
trafficState.setChannelNumber( channelNumber );
|
||||
trafficState.setFromTalkgroup( mpt.getFromID() );
|
||||
trafficState.setToTalkgroup( mpt.getToID() );
|
||||
|
||||
/* Add this control channel as message listener on the
|
||||
* traffic channel so we can receive call tear-down
|
||||
* messages */
|
||||
traffic.addListener( (Listener<Message>)this );
|
||||
|
||||
CallEventType type = traffic.isProcessing() ?
|
||||
CallEventType.CALL_START :
|
||||
CallEventType.CALL_START_NO_TUNER;
|
||||
|
||||
/*
|
||||
* Set the traffic channel's call event model to
|
||||
* share the control channel's call event model
|
||||
*/
|
||||
traffic.getProcessingChain().getChannelState()
|
||||
.setCallEventModel( mCallEventModel );
|
||||
|
||||
mCallEventModel.add(
|
||||
new MPT1327CallEvent.Builder( type )
|
||||
.aliasList( traffic.getProcessingChain().getAliasList() )
|
||||
.channel( channelNumber )
|
||||
.frequency( mChannelMap.getFrequency( channelNumber ) )
|
||||
.from( mpt.getFromID() )
|
||||
.to( mpt.getToID() )
|
||||
.build() );
|
||||
}
|
||||
|
||||
int frequency = mChannelMap.getFrequency( channelNumber );
|
||||
|
||||
break;
|
||||
case CLEAR:
|
||||
case MAINT:
|
||||
if( mChannelType == ChannelType.TRAFFIC )
|
||||
{
|
||||
fade( CallEventType.CALL_END );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the fade event so that we can generate a call end event
|
||||
*/
|
||||
@Override
|
||||
public void fade( final CallEventType type )
|
||||
{
|
||||
/*
|
||||
* We can receive multiple call tear-down messages -- only post a call
|
||||
* end event for the one that can change the state to fade
|
||||
*/
|
||||
if( getState().canChangeTo( State.FADE ) )
|
||||
{
|
||||
mCallEventModel.add(
|
||||
new MPT1327CallEvent.Builder( type )
|
||||
.aliasList( getAliasList() )
|
||||
.channel( mChannelNumber )
|
||||
.frequency( mChannelMap.getFrequency( mChannelNumber ) )
|
||||
.from( mFromTalkgroup )
|
||||
.to( mToTalkgroup )
|
||||
.build() );
|
||||
}
|
||||
|
||||
super.fade( type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the ConventionalChannelState always unsquelched
|
||||
*/
|
||||
public void addListener( SquelchListener listener )
|
||||
{
|
||||
super.addListener( listener );
|
||||
|
||||
super.setSquelchState( SquelchState.UNSQUELCH );
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
mFromTalkgroup = null;
|
||||
broadcastChange( ChangedAttribute.FROM_TALKGROUP );
|
||||
mToTalkgroup = null;
|
||||
broadcastChange( ChangedAttribute.TO_TALKGROUP );
|
||||
|
||||
super.reset();
|
||||
}
|
||||
|
||||
public int getSite()
|
||||
{
|
||||
return mSite;
|
||||
}
|
||||
|
||||
public ChannelMap getChannelMap()
|
||||
{
|
||||
return mChannelMap;
|
||||
}
|
||||
|
||||
public void setChannelMap( ChannelMap channelMap )
|
||||
{
|
||||
mChannelMap = channelMap;
|
||||
}
|
||||
|
||||
public String getFromTalkgroup()
|
||||
{
|
||||
return mFromTalkgroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the talkgroup. This is used primarily for traffic channels since
|
||||
* the talkgroup will already have been identified prior to the traffic
|
||||
* channel being created.
|
||||
*/
|
||||
public void setFromTalkgroup( String fromTalkgroup )
|
||||
{
|
||||
mFromTalkgroup = fromTalkgroup;
|
||||
|
||||
broadcastChange( ChangedAttribute.FROM_TALKGROUP );
|
||||
}
|
||||
|
||||
public String getToTalkgroup()
|
||||
{
|
||||
return mToTalkgroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the talkgroup. This is used primarily for traffic channels since
|
||||
* the talkgroup will already have been identified prior to the traffic
|
||||
* channel being created.
|
||||
*/
|
||||
public void setToTalkgroup( String toTalkgroup )
|
||||
{
|
||||
mToTalkgroup = toTalkgroup;
|
||||
|
||||
broadcastChange( ChangedAttribute.TO_TALKGROUP );
|
||||
}
|
||||
|
||||
public int getChannelNumber()
|
||||
{
|
||||
return mChannelNumber;
|
||||
}
|
||||
/**
|
||||
* Set the channel number. This is used primarily for traffic channels since
|
||||
* the channel will already have been identified prior to the traffic
|
||||
* channel being created.
|
||||
*/
|
||||
public void setChannelNumber( int channel )
|
||||
{
|
||||
mChannelNumber = channel;
|
||||
|
||||
broadcastChange( ChangedAttribute.CHANNEL_NUMBER );
|
||||
}
|
||||
|
||||
public String getAliasListName()
|
||||
{
|
||||
return mProcessingChain.getChannel().getAliasListName();
|
||||
}
|
||||
|
||||
private Channel getTrafficChannel( int channelNumber, String aliasListName )
|
||||
{
|
||||
Channel traffic = new Channel( "Traffic Channel " + channelNumber,
|
||||
ChannelType.TRAFFIC );
|
||||
|
||||
traffic.setResourceManager( getProcessingChain().getResourceManager() );
|
||||
|
||||
SourceConfigTuner source = new SourceConfigTuner();
|
||||
|
||||
int frequency = mChannelMap.getFrequency( channelNumber );
|
||||
|
||||
source.setFrequency( frequency );
|
||||
|
||||
traffic.setSourceConfiguration( source );
|
||||
|
||||
DecodeConfigMPT1327 decode = new DecodeConfigMPT1327();
|
||||
traffic.setDecodeConfiguration( decode );
|
||||
|
||||
traffic.setAliasListName( aliasListName );
|
||||
|
||||
return traffic;
|
||||
}
|
||||
}
|
||||
283
src/decode/mpt1327/MPT1327Decoder.java
Normal file
283
src/decode/mpt1327/MPT1327Decoder.java
Normal file
@@ -0,0 +1,283 @@
|
||||
/*******************************************************************************
|
||||
* 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 decode.mpt1327;
|
||||
|
||||
import instrument.Instrumentable;
|
||||
import instrument.tap.Tap;
|
||||
import instrument.tap.stream.BinaryTap;
|
||||
import instrument.tap.stream.FloatTap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import sample.Broadcaster;
|
||||
import source.Source.SampleType;
|
||||
import alias.AliasList;
|
||||
import bits.MessageFramer;
|
||||
import bits.SyncPattern;
|
||||
import decode.Decoder;
|
||||
import decode.DecoderType;
|
||||
import dsp.filter.DCRemovalFilter;
|
||||
import dsp.filter.FilterFactory;
|
||||
import dsp.filter.Filters;
|
||||
import dsp.filter.FloatFIRFilter;
|
||||
import dsp.filter.FloatHalfBandFilter;
|
||||
import dsp.filter.Window.WindowType;
|
||||
import dsp.fsk.FSK2Decoder;
|
||||
import dsp.fsk.FSK2Decoder.Output;
|
||||
import dsp.nbfm.NBFMDemodulator;
|
||||
|
||||
/**
|
||||
* MPT1327 Decoder - 1200 baud 2FSK decoder that can process 48k sample rate
|
||||
* complex or floating point samples and output fully framed MPT1327 control and
|
||||
* traffic messages.
|
||||
*/
|
||||
public class MPT1327Decoder extends Decoder implements Instrumentable
|
||||
{
|
||||
/* Determines how quickly the DC remove filter responds */
|
||||
private static final double sDC_REMOVAL_RATIO = 0.95;
|
||||
|
||||
/* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */
|
||||
private static final int sDECIMATED_SAMPLE_RATE = 24000;
|
||||
|
||||
/* Baud or Symbol Rate */
|
||||
private static final int sSYMBOL_RATE = 1200;
|
||||
|
||||
/* Message length -- longest possible message is:
|
||||
* 4xREVS + 16xSYNC + 64xADD1 + 64xDCW1 + 64xDCW2 + 64xDCW3 + 64xDCW4 */
|
||||
private static final int sMESSAGE_LENGTH = 350;
|
||||
|
||||
/* Instrumentation Taps */
|
||||
private static final String INSTRUMENT_INPUT = "Tap Point: Input";
|
||||
private static final String INSTRUMENT_HB1_FILTER_TO_LOW_PASS =
|
||||
"Tap Point: Half-band Decimation Filter > < Low Pass Filter";
|
||||
private static final String INSTRUMENT_LOW_PASS_TO_DECODER =
|
||||
"Tap Point: Low Pass Filter > < Decoder";
|
||||
private static final String INSTRUMENT_DECODER_TO_FRAMER =
|
||||
"Tap Point: Decoder > < Sync Detect/Message Framer";
|
||||
private List<Tap> mAvailableTaps;
|
||||
|
||||
private NBFMDemodulator mNBFMDemodulator;
|
||||
private FloatHalfBandFilter mDecimationFilter;
|
||||
private FloatFIRFilter mLowPassFilter;
|
||||
private DCRemovalFilter mDCRemovalFilter;
|
||||
private FSK2Decoder mFSKDecoder;
|
||||
private Broadcaster<Boolean> mSymbolBroadcaster;
|
||||
private MessageFramer mControlMessageFramer;
|
||||
private MessageFramer mTrafficMessageFramer;
|
||||
private MPT1327MessageProcessor mMessageProcessor;
|
||||
|
||||
public MPT1327Decoder( SampleType sampleType, AliasList aliasList )
|
||||
{
|
||||
super( sampleType );
|
||||
|
||||
/* If we're receiving complex samples, do FM demodulation and DC removal
|
||||
* and feed the output back to this decoder */
|
||||
if( mSourceSampleType == SampleType.COMPLEX )
|
||||
{
|
||||
/* I/Q low pass filtering narrow band FM demodulator */
|
||||
mNBFMDemodulator = new NBFMDemodulator(
|
||||
FilterFactory.getLowPass( 48000, 4000, 73, WindowType.HAMMING ),
|
||||
1.0002 );
|
||||
|
||||
this.addComplexListener( mNBFMDemodulator );
|
||||
|
||||
/* DC removal filter */
|
||||
mDCRemovalFilter = new DCRemovalFilter( sDC_REMOVAL_RATIO );
|
||||
|
||||
if( mNBFMDemodulator != null )
|
||||
{
|
||||
mNBFMDemodulator.addListener( mDCRemovalFilter );
|
||||
mDCRemovalFilter.setListener( this.getFloatReceiver() );
|
||||
}
|
||||
}
|
||||
|
||||
/* Demodulated float sample processing */
|
||||
|
||||
/* Decimation filter - 48000 / 2 = 24000 output */
|
||||
mDecimationFilter = new FloatHalfBandFilter(
|
||||
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
|
||||
addFloatListener( mDecimationFilter );
|
||||
|
||||
/* Low pass filter: 2kHz to pass the 1200 & 1800 Hz FSK */
|
||||
mLowPassFilter = new FloatFIRFilter(
|
||||
FilterFactory.getLowPass( 24000, //sampleRate,
|
||||
2000, //passFrequency,
|
||||
4000, //stopFrequency,
|
||||
60, //attenuation,
|
||||
WindowType.HANNING, //windowType,
|
||||
true ) //forceOddLength
|
||||
, 2.0 ); //Gain
|
||||
mDecimationFilter.setListener( mLowPassFilter );
|
||||
|
||||
/* 2FSK Decoder with output inverted */
|
||||
mFSKDecoder = new FSK2Decoder( 24000, 1200, Output.INVERTED );
|
||||
mLowPassFilter.setListener( mFSKDecoder );
|
||||
|
||||
mSymbolBroadcaster = new Broadcaster<Boolean>();
|
||||
mFSKDecoder.setListener( mSymbolBroadcaster );
|
||||
|
||||
/* Message framer for control channel messages */
|
||||
mControlMessageFramer =
|
||||
new MessageFramer( SyncPattern.MPT1327_CONTROL.getPattern(),
|
||||
sMESSAGE_LENGTH );
|
||||
mSymbolBroadcaster.addListener( mControlMessageFramer );
|
||||
|
||||
/* Message framer for traffic channel massages */
|
||||
mTrafficMessageFramer =
|
||||
new MessageFramer( SyncPattern.MPT1327_TRAFFIC.getPattern(),
|
||||
sMESSAGE_LENGTH );
|
||||
mSymbolBroadcaster.addListener( mTrafficMessageFramer );
|
||||
|
||||
/* Fully decoded and framed messages processor */
|
||||
mMessageProcessor = new MPT1327MessageProcessor( aliasList );
|
||||
mMessageProcessor.addMessageListener( this );
|
||||
mControlMessageFramer.addMessageListener( mMessageProcessor );
|
||||
mTrafficMessageFramer.addMessageListener( mMessageProcessor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecoderType getType()
|
||||
{
|
||||
return DecoderType.MPT1327;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup method
|
||||
*/
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
|
||||
mSymbolBroadcaster.dispose();
|
||||
|
||||
mControlMessageFramer.dispose();
|
||||
|
||||
if( mDCRemovalFilter != null )
|
||||
{
|
||||
mDCRemovalFilter.dispose();
|
||||
}
|
||||
|
||||
if( mNBFMDemodulator != null )
|
||||
{
|
||||
mNBFMDemodulator.dispose();
|
||||
}
|
||||
|
||||
mFSKDecoder.dispose();
|
||||
|
||||
mDecimationFilter.dispose();
|
||||
|
||||
mLowPassFilter.dispose();
|
||||
|
||||
mMessageProcessor.dispose();
|
||||
|
||||
|
||||
mTrafficMessageFramer.dispose();
|
||||
}
|
||||
|
||||
/* Instrumentation Taps */
|
||||
@Override
|
||||
public List<Tap> getTaps()
|
||||
{
|
||||
if( mAvailableTaps == null )
|
||||
{
|
||||
mAvailableTaps = new ArrayList<Tap>();
|
||||
|
||||
mAvailableTaps.add(
|
||||
new FloatTap( INSTRUMENT_INPUT, 0, 1.0f ) );
|
||||
mAvailableTaps.add(
|
||||
new FloatTap( INSTRUMENT_HB1_FILTER_TO_LOW_PASS, 0, 0.5f ) );
|
||||
mAvailableTaps.add(
|
||||
new FloatTap( INSTRUMENT_LOW_PASS_TO_DECODER, 0, 0.5f ) );
|
||||
mAvailableTaps.add(
|
||||
new BinaryTap( INSTRUMENT_DECODER_TO_FRAMER, 0, 0.025f ) );
|
||||
|
||||
/* Add the taps from the FSK decoder */
|
||||
mAvailableTaps.addAll( mFSKDecoder.getTaps() );
|
||||
}
|
||||
|
||||
return mAvailableTaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTap( Tap tap )
|
||||
{
|
||||
/* Send request to decoder */
|
||||
mFSKDecoder.addTap( tap );
|
||||
|
||||
switch( tap.getName() )
|
||||
{
|
||||
case INSTRUMENT_INPUT:
|
||||
FloatTap inputTap = (FloatTap)tap;
|
||||
if( mNBFMDemodulator != null )
|
||||
{
|
||||
mNBFMDemodulator.addListener( inputTap );
|
||||
}
|
||||
else
|
||||
{
|
||||
addFloatListener( inputTap );
|
||||
}
|
||||
break;
|
||||
case INSTRUMENT_HB1_FILTER_TO_LOW_PASS:
|
||||
FloatTap hb1Tap = (FloatTap)tap;
|
||||
mDecimationFilter.setListener( hb1Tap );
|
||||
hb1Tap.setListener( mLowPassFilter );
|
||||
break;
|
||||
case INSTRUMENT_LOW_PASS_TO_DECODER:
|
||||
FloatTap lowTap = (FloatTap)tap;
|
||||
mLowPassFilter.setListener( lowTap );
|
||||
lowTap.setListener( mFSKDecoder );
|
||||
break;
|
||||
case INSTRUMENT_DECODER_TO_FRAMER:
|
||||
BinaryTap decoderTap = (BinaryTap)tap;
|
||||
mFSKDecoder.setListener( decoderTap );
|
||||
decoderTap.setListener( mSymbolBroadcaster );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTap( Tap tap )
|
||||
{
|
||||
mFSKDecoder.removeTap( tap );
|
||||
|
||||
switch( tap.getName() )
|
||||
{
|
||||
case INSTRUMENT_INPUT:
|
||||
FloatTap inputTap = (FloatTap)tap;
|
||||
if( mNBFMDemodulator != null )
|
||||
{
|
||||
mNBFMDemodulator.removeListener( inputTap );
|
||||
}
|
||||
else
|
||||
{
|
||||
removeFloatListener( inputTap );
|
||||
}
|
||||
break;
|
||||
case INSTRUMENT_HB1_FILTER_TO_LOW_PASS:
|
||||
mDecimationFilter.setListener( mLowPassFilter );
|
||||
break;
|
||||
case INSTRUMENT_LOW_PASS_TO_DECODER:
|
||||
mLowPassFilter.setListener( mFSKDecoder );
|
||||
break;
|
||||
case INSTRUMENT_DECODER_TO_FRAMER:
|
||||
mFSKDecoder.setListener( mSymbolBroadcaster );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
103
src/decode/mpt1327/MPT1327Editor.java
Normal file
103
src/decode/mpt1327/MPT1327Editor.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*******************************************************************************
|
||||
* 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 decode.mpt1327;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import controller.channel.ChannelMap;
|
||||
import controller.channel.ChannelNode;
|
||||
import decode.DecodeEditor;
|
||||
import decode.config.DecodeConfigMPT1327;
|
||||
import decode.config.DecodeConfiguration;
|
||||
|
||||
public class MPT1327Editor extends DecodeEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<ChannelMap> mComboChannelMaps;
|
||||
private ChannelNode mChannelNode;
|
||||
|
||||
public MPT1327Editor( DecodeConfiguration config, ChannelNode channelNode )
|
||||
{
|
||||
super( config );
|
||||
|
||||
mChannelNode = channelNode;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
/**
|
||||
* ComboBox: Alias Lists
|
||||
*/
|
||||
ArrayList<ChannelMap> maps = mChannelNode.getModel().getResourceManager()
|
||||
.getPlaylistManager().getPlayist().getChannelMapList().getChannelMap();
|
||||
|
||||
ChannelMap[] mapArray = maps.toArray( new ChannelMap[ maps.size() ] );
|
||||
|
||||
mComboChannelMaps = new JComboBox<ChannelMap>();
|
||||
mComboChannelMaps.setModel(
|
||||
new DefaultComboBoxModel<ChannelMap>( mapArray ) );
|
||||
|
||||
add( new JLabel( "Channel Map" ), "wrap" );
|
||||
add( mComboChannelMaps, "wrap" );
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
ChannelMap selected = (ChannelMap)mComboChannelMaps.getSelectedItem();
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
((DecodeConfigMPT1327)mConfig).setChannelMapName( selected.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
String name = ((DecodeConfigMPT1327)mConfig).getChannelMapName();
|
||||
|
||||
ChannelMap selected = null;
|
||||
|
||||
if( name != null )
|
||||
{
|
||||
for( ChannelMap map: mChannelNode.getModel().getResourceManager()
|
||||
.getPlaylistManager().getPlayist().getChannelMapList()
|
||||
.getChannelMap() )
|
||||
{
|
||||
if( map.getName().equalsIgnoreCase( name ) )
|
||||
{
|
||||
selected = map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mComboChannelMaps.setSelectedItem( selected );
|
||||
mComboChannelMaps.requestFocus();
|
||||
mComboChannelMaps.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
986
src/decode/mpt1327/MPT1327Message.java
Normal file
986
src/decode/mpt1327/MPT1327Message.java
Normal file
@@ -0,0 +1,986 @@
|
||||
/*******************************************************************************
|
||||
* 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 decode.mpt1327;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.BitSet;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import map.Plottable;
|
||||
import message.Message;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import crc.CRC;
|
||||
import crc.CRCFleetsync;
|
||||
|
||||
public class MPT1327Message extends Message
|
||||
{
|
||||
private static DecimalFormat mDecimalFormatter = new DecimalFormat("#.#####");
|
||||
private static SimpleDateFormat mSDF = new SimpleDateFormat( "yyyyMMdd HHmmss" );
|
||||
|
||||
//Calendar to use in calculating time hacks
|
||||
Calendar mCalendar = new GregorianCalendar();
|
||||
|
||||
//Message parts are identified in big-endian order for correct translation
|
||||
private static int BLOCK_1_START = 20;
|
||||
private static int BLOCK_2_START = 84;
|
||||
private static int BLOCK_3_START = 148;
|
||||
private static int BLOCK_4_START = 212;
|
||||
private static int BLOCK_5_START = 276;
|
||||
private static int BLOCK_5_END = 340;
|
||||
private static int[] REVS = { 0,1,2,3 };
|
||||
private static int[] SYNC = { 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 };
|
||||
|
||||
/* Block 1 Fields */
|
||||
private static int[] B1_PREFIX = { 21,22,23,24,25,26,27 };
|
||||
private static int[] B1_IDENT1 = { 28,29,30,31,32,33,34,35,36,37,38,39,40 };
|
||||
private static int[] B1_IDENT2 = { 53,54,55,56,57,58,59,60,61,62,63,64,65 };
|
||||
private static int[] B1_GTC_CHAN = { 43,44,45,46,47,48,49,50,51,52 };
|
||||
private static int[] B1_MESSAGE_TYPE = { 41,42,43,44,45,46,47,48,49 };
|
||||
private static int[] B1_STATUS_MESSAGE = { 66,67,68,69,70 };
|
||||
private static int[] B1_SYSTEM_ID = { 26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 };
|
||||
private static int[] B1_SYSDEF = { 21,22,23,24,25 };
|
||||
private static int[] B1_CHANNEL = { 35,36,37,38,39,40,41,42,43,44 };
|
||||
private static int[] B1_TRAFFIC_CHANNEL = { 21,22,23,24,25,26,27,28,29,30 };
|
||||
private static int[] B1_CONTROL_CHANNEL = { 31,32,33,34,35,36,37,38,39,40 };
|
||||
private static int[] B1_ADJSITE = { 49,50,51,52 };
|
||||
|
||||
/* Block 2 Fields */
|
||||
private static int[] B2_SYSTEM_ID = { 85,86,87,88,89,90,91,92,93,94,95,96,97,98,99 };
|
||||
private static int[] B2_PREFIX = { 112,113,114,115,116,117,118 };
|
||||
private static int[] B2_IDENT2 = { 119,120,121,122,123,124,125,126,127,128,129,130,131 };
|
||||
|
||||
private BitSetBuffer mMessage;
|
||||
private CRC[] mCRC = new CRC[ 5 ];
|
||||
private AliasList mAliasList;
|
||||
private MPTMessageType mMessageType;
|
||||
|
||||
public MPT1327Message( BitSetBuffer message, AliasList list )
|
||||
{
|
||||
mMessage = message;
|
||||
mAliasList = list;
|
||||
|
||||
checkParity( 0, BLOCK_1_START, BLOCK_2_START );
|
||||
|
||||
if( isValid() )
|
||||
{
|
||||
mMessageType = getMessageType();
|
||||
|
||||
switch( mMessageType )
|
||||
{
|
||||
/* 1 data block messages */
|
||||
case CLEAR:
|
||||
case MAINT:
|
||||
case MOVE:
|
||||
break;
|
||||
/* 2 data block messages */
|
||||
case AHYQ:
|
||||
case ALH:
|
||||
checkParity( 1, BLOCK_2_START, BLOCK_3_START );
|
||||
break;
|
||||
/* 3 data block messages */
|
||||
/* 4 data block messages */
|
||||
case ACKT:
|
||||
checkParity( 1, BLOCK_2_START, BLOCK_3_START );
|
||||
checkParity( 2, BLOCK_3_START, BLOCK_4_START );
|
||||
checkParity( 3, BLOCK_4_START, BLOCK_5_START );
|
||||
break;
|
||||
/* 5 data block messages */
|
||||
case AHYC:
|
||||
checkParity( 1, BLOCK_2_START, BLOCK_3_START );
|
||||
checkParity( 2, BLOCK_3_START, BLOCK_4_START );
|
||||
checkParity( 3, BLOCK_4_START, BLOCK_5_START );
|
||||
checkParity( 3, BLOCK_5_START, BLOCK_5_END );
|
||||
break;
|
||||
case ACK:
|
||||
case ACKB:
|
||||
case ACKE:
|
||||
case ACKI:
|
||||
case ACKQ:
|
||||
case ACKV:
|
||||
case ACKX:
|
||||
case AHOY:
|
||||
case AHYP:
|
||||
case AHYX:
|
||||
case ALHD:
|
||||
case ALHE:
|
||||
case ALHF:
|
||||
case ALHR:
|
||||
case ALHS:
|
||||
case ALHX:
|
||||
case BCAST:
|
||||
case GTC:
|
||||
case MARK:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mMessageType = MPTMessageType.UNKN;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkParity( int section, int start, int end )
|
||||
{
|
||||
mCRC[ section ] = detectAndCorrect( start, end );
|
||||
}
|
||||
|
||||
private CRC detectAndCorrect( int start, int end )
|
||||
{
|
||||
BitSet original = mMessage.get( start, end );
|
||||
|
||||
CRC retVal = CRCFleetsync.check( original );
|
||||
|
||||
//Attempt to correct single-bit errors
|
||||
if( retVal == CRC.FAILED_PARITY )
|
||||
{
|
||||
int[] errorBitPositions = CRCFleetsync.findBitErrors( original );
|
||||
|
||||
if( errorBitPositions != null )
|
||||
{
|
||||
for( int errorBitPosition: errorBitPositions )
|
||||
{
|
||||
mMessage.flip( start + errorBitPosition );
|
||||
}
|
||||
|
||||
retVal = CRC.CORRECTED;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representing results of the parity check
|
||||
*
|
||||
* [P] = passes parity check
|
||||
* [f] = fails parity check
|
||||
* [C] = corrected message
|
||||
* [-] = message section not present
|
||||
*/
|
||||
public String getParity()
|
||||
{
|
||||
return "[" + CRC.format( mCRC ) + "]";
|
||||
}
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
return mCRC[ 0 ] == CRC.PASSED ||
|
||||
mCRC[ 0 ] == CRC.CORRECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mSDF.format( new Date() ) );
|
||||
|
||||
sb.append( " MPT1327 " );
|
||||
|
||||
sb.append( getParity() );
|
||||
|
||||
sb.append( " " );
|
||||
|
||||
sb.append( getMessage() );
|
||||
|
||||
sb.append( getFiller( sb, 100 ) );
|
||||
|
||||
sb.append( " [" + mMessage.toString() + "]" );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public MPTMessageType getMessageType()
|
||||
{
|
||||
int type = mMessage.getInt( B1_MESSAGE_TYPE );
|
||||
|
||||
return MPTMessageType.fromNumber( type );
|
||||
}
|
||||
|
||||
public int getSiteID()
|
||||
{
|
||||
if( mMessageType == MPTMessageType.BCAST )
|
||||
{
|
||||
return mMessage.getInt( B1_SYSTEM_ID );
|
||||
}
|
||||
else if( mMessageType == MPTMessageType.ALH )
|
||||
{
|
||||
return mMessage.getInt( B2_SYSTEM_ID );
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasSystemID()
|
||||
{
|
||||
return getSiteID() != 0;
|
||||
}
|
||||
|
||||
public SystemDefinition getSystemDefinition()
|
||||
{
|
||||
int sysdef = mMessage.getInt( B1_SYSDEF );
|
||||
|
||||
return SystemDefinition.fromNumber( sysdef );
|
||||
}
|
||||
|
||||
public int getChannel()
|
||||
{
|
||||
switch( mMessageType )
|
||||
{
|
||||
case CLEAR:
|
||||
return mMessage.getInt( B1_TRAFFIC_CHANNEL );
|
||||
case GTC:
|
||||
return mMessage.getInt( B1_GTC_CHAN );
|
||||
default:
|
||||
return mMessage.getInt( B1_CHANNEL );
|
||||
}
|
||||
}
|
||||
|
||||
public int getReturnToChannel()
|
||||
{
|
||||
if( mMessageType == MPTMessageType.CLEAR )
|
||||
{
|
||||
return mMessage.getInt( B1_CONTROL_CHANNEL );
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int getAdjacentSiteSerialNumber()
|
||||
{
|
||||
return mMessage.getInt( B1_ADJSITE );
|
||||
}
|
||||
|
||||
public int getPrefix()
|
||||
{
|
||||
return mMessage.getInt( B1_PREFIX );
|
||||
}
|
||||
|
||||
public int getBlock2Prefix()
|
||||
{
|
||||
return mMessage.getInt( B2_PREFIX );
|
||||
}
|
||||
|
||||
public int getIdent1()
|
||||
{
|
||||
return mMessage.getInt( B1_IDENT1 );
|
||||
}
|
||||
|
||||
public int getIdent2()
|
||||
{
|
||||
return mMessage.getInt( B1_IDENT2 );
|
||||
}
|
||||
|
||||
public int getBlock2Ident2()
|
||||
{
|
||||
return mMessage.getInt( B2_IDENT2 );
|
||||
}
|
||||
|
||||
public String getStatusMessage()
|
||||
{
|
||||
int status = mMessage.getInt( B1_STATUS_MESSAGE );
|
||||
|
||||
switch( status )
|
||||
{
|
||||
case 0:
|
||||
return "STATUS: Request Speech Call";
|
||||
case 31:
|
||||
return "STATUS: Cancel Request Speech Call";
|
||||
default:
|
||||
return "STATUS: " + status;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns spaces to the fill the string builder to ensure length is >= index
|
||||
*/
|
||||
public String getFiller( StringBuilder sb, int index )
|
||||
{
|
||||
if( sb.length() < index )
|
||||
{
|
||||
return String.format( "%" + ( index - sb.length() ) + "s", " " );
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads spaces onto the end of the value to make it 'places' long
|
||||
*/
|
||||
public String pad( String value, int places, String padCharacter )
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( value );
|
||||
|
||||
while( sb.length() < places )
|
||||
{
|
||||
sb.append( padCharacter );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads an integer value with additional zeroes to make it decimalPlaces long
|
||||
*/
|
||||
public String format( int number, int decimalPlaces )
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int paddingRequired = decimalPlaces - ( String.valueOf( number ).length() );
|
||||
|
||||
for( int x = 0; x < paddingRequired; x++)
|
||||
{
|
||||
sb.append( "0" );
|
||||
}
|
||||
|
||||
sb.append( number );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( pad( mMessageType.toString(), 5, " " ) );
|
||||
|
||||
switch( mMessageType )
|
||||
{
|
||||
case ACK:
|
||||
sb.append( " MESSAGE ACKNOWLEDGED" );
|
||||
|
||||
if( hasFromID() )
|
||||
{
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getFromID() );
|
||||
}
|
||||
break;
|
||||
case ACKI:
|
||||
sb.append( " SYSTEM:" );
|
||||
sb.append( format( getSiteID(), 5 ) );
|
||||
|
||||
sb.append( " MESSAGE ACKNOWLEDGED - MORE TO FOLLOW" );
|
||||
|
||||
if( hasFromID() )
|
||||
{
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getFromID() );
|
||||
}
|
||||
|
||||
if( hasToID() )
|
||||
{
|
||||
sb.append( " TO:" );
|
||||
sb.append( getToID() );
|
||||
}
|
||||
break;
|
||||
case ACKT:
|
||||
sb.append( " SITE:" );
|
||||
sb.append( format( getSiteID(), 5 ) );
|
||||
|
||||
sb.append( " LONG ACK MESSAGE" );
|
||||
|
||||
if( hasFromID() )
|
||||
{
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getFromID() );
|
||||
}
|
||||
|
||||
if( hasToID() )
|
||||
{
|
||||
sb.append( " TO:" );
|
||||
sb.append( getToID() );
|
||||
}
|
||||
|
||||
sb.append( "**********************************" );
|
||||
break;
|
||||
case ACKQ:
|
||||
sb.append( " SYSTEM:" );
|
||||
sb.append( format( getSiteID(), 5 ) );
|
||||
|
||||
sb.append( " CALL QUEUED FROM:" );
|
||||
|
||||
if( hasFromID() )
|
||||
{
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getFromID() );
|
||||
}
|
||||
|
||||
if( hasToID() )
|
||||
{
|
||||
sb.append( " TO:" );
|
||||
sb.append( getToID() );
|
||||
}
|
||||
break;
|
||||
case ACKX:
|
||||
sb.append( " SYSTEM:" );
|
||||
sb.append( format( getSiteID(), 5 ) );
|
||||
|
||||
sb.append( " MESSAGE REJECTED FROM:" );
|
||||
|
||||
if( hasFromID() )
|
||||
{
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getFromID() );
|
||||
}
|
||||
|
||||
if( hasToID() )
|
||||
{
|
||||
sb.append( " TO:" );
|
||||
sb.append( getToID() );
|
||||
}
|
||||
break;
|
||||
case AHYC:
|
||||
/* SDM */
|
||||
sb.append( " SHORT DATA INVITATION MESSAGE ********* " );
|
||||
break;
|
||||
case AHYQ:
|
||||
/* Status Message */
|
||||
sb.append( " STATUS MESSAGE" );
|
||||
|
||||
if( hasFromID() )
|
||||
{
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getFromID() );
|
||||
}
|
||||
|
||||
if( hasToID() )
|
||||
{
|
||||
sb.append( " TO:" );
|
||||
sb.append( getToID() );
|
||||
}
|
||||
sb.append( " " );
|
||||
sb.append( getStatusMessage() );
|
||||
break;
|
||||
case ALH:
|
||||
case ALHD:
|
||||
case ALHS:
|
||||
case ALHE:
|
||||
case ALHR:
|
||||
case ALHX:
|
||||
case ALHF:
|
||||
sb.append( " SYSTEM:" );
|
||||
sb.append( format( getSiteID(), 5 ) );
|
||||
|
||||
if( hasToID() )
|
||||
{
|
||||
sb.append( " ID:" );
|
||||
sb.append( getToID() );
|
||||
}
|
||||
break;
|
||||
case BCAST:
|
||||
SystemDefinition sysdef = getSystemDefinition();
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( sysdef.getLabel() );
|
||||
|
||||
switch( sysdef )
|
||||
{
|
||||
case ANNOUNCE_CONTROL_CHANNEL:
|
||||
case WITHDRAW_CONTROL_CHANNEL:
|
||||
sb.append( " CHAN:" );
|
||||
sb.append( getChannel() );
|
||||
break;
|
||||
case BROADCAST_ADJACENT_SITE_CONTROL_CHANNEL_NUMBER:
|
||||
sb.append( " CHAN:" );
|
||||
sb.append( getChannel() );
|
||||
sb.append( " SER:" );
|
||||
sb.append( getAdjacentSiteSerialNumber() );
|
||||
//debug
|
||||
sb.append( " *************************" );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CLEAR:
|
||||
sb.append( " TRAFFIC CHANNEL:" );
|
||||
sb.append( getChannel() );
|
||||
sb.append( " RETURN TO CONTROL CHANNEL:" );
|
||||
sb.append( getReturnToChannel() );
|
||||
break;
|
||||
case GTC:
|
||||
if( hasFromID() )
|
||||
{
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getFromID() );
|
||||
}
|
||||
|
||||
if( hasToID() )
|
||||
{
|
||||
sb.append( " TO:" );
|
||||
sb.append( getToID() );
|
||||
}
|
||||
|
||||
sb.append( " CHAN:" );
|
||||
sb.append( getChannel() );
|
||||
break;
|
||||
case MAINT:
|
||||
if( hasToID() )
|
||||
{
|
||||
sb.append( " ID:" );
|
||||
sb.append( getToID() );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBinaryMessage()
|
||||
{
|
||||
return mMessage.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return "MPT-1327";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFromID()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int ident2 = getIdent2();
|
||||
|
||||
IdentType type = IdentType.fromIdent( ident2 );
|
||||
|
||||
/* Inter-Prefix - the from and to idents are different prefixes */
|
||||
if( type == IdentType.IPFIXI )
|
||||
{
|
||||
sb.append( format( getBlock2Prefix(), 3 ) );
|
||||
sb.append( "-" );
|
||||
sb.append( format( getBlock2Ident2(), 4) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( format( getPrefix(), 3 ) );
|
||||
sb.append( "-" );
|
||||
sb.append( format( ident2, 4) );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean hasFromID()
|
||||
{
|
||||
return getFromID() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToID()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int prefix = getPrefix();
|
||||
int ident = getIdent1();
|
||||
|
||||
switch( IdentType.fromIdent( ident ) )
|
||||
{
|
||||
case USER:
|
||||
sb.append( format( prefix, 3 ) );
|
||||
sb.append( "-" );
|
||||
sb.append( format( ident, 4) );
|
||||
break;
|
||||
case IPFIXI:
|
||||
sb.append( "INTER-PREFIX" );
|
||||
break;
|
||||
case ALLI:
|
||||
sb.append( "ALL RADIOS" );
|
||||
break;
|
||||
case PABXI:
|
||||
sb.append( "PABX EXT" );
|
||||
break;
|
||||
case PSTNSI1:
|
||||
case PSTNSI2:
|
||||
case PSTNSI3:
|
||||
case PSTNSI4:
|
||||
case PSTNSI5:
|
||||
case PSTNSI6:
|
||||
case PSTNSI7:
|
||||
case PSTNSI8:
|
||||
case PSTNSI9:
|
||||
case PSTNSI10:
|
||||
case PSTNSI11:
|
||||
case PSTNSI12:
|
||||
case PSTNSI13:
|
||||
case PSTNSI14:
|
||||
case PSTNSI15:
|
||||
sb.append( "PRE-DEFINED PSTN" );
|
||||
break;
|
||||
case PSTNGI:
|
||||
sb.append( "PSTN GATEWAY" );
|
||||
break;
|
||||
case TSCI:
|
||||
sb.append( "CONTROLLER" );
|
||||
break;
|
||||
case DIVERTI:
|
||||
sb.append( "CALL DIVERT" );
|
||||
break;
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean hasToID()
|
||||
{
|
||||
return getToID() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
if( hasToID() )
|
||||
{
|
||||
return mAliasList.getMPT1327Alias( getToID() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorStatus()
|
||||
{
|
||||
return getParity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plottable getPlottable()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public enum IdentType
|
||||
{
|
||||
ALLI( "All Subscribers" ),
|
||||
DIVERTI( "Divert" ),
|
||||
DNI( "Data Network Gateway" ),
|
||||
DUMMYI( "Dummy Ident" ),
|
||||
INCI( "Include in Call" ),
|
||||
IPFIXI( "Inter-Prefix" ),
|
||||
PABXI( "PABX Gateway" ),
|
||||
PSTNGI( "PSTN Gateway" ),
|
||||
PSTNSI1( "PSTN or Network 1" ),
|
||||
PSTNSI2( "PSTN or Network 2" ),
|
||||
PSTNSI3( "PSTN or Network 3" ),
|
||||
PSTNSI4( "PSTN or Network 4" ),
|
||||
PSTNSI5( "PSTN or Network 5" ),
|
||||
PSTNSI6( "PSTN or Network 6" ),
|
||||
PSTNSI7( "PSTN or Network 7" ),
|
||||
PSTNSI8( "PSTN or Network 8" ),
|
||||
PSTNSI9( "PSTN or Network 9" ),
|
||||
PSTNSI10( "PSTN or Network 10" ),
|
||||
PSTNSI11( "PSTN or Network 11" ),
|
||||
PSTNSI12( "PSTN or Network 12" ),
|
||||
PSTNSI13( "PSTN or Network 13" ),
|
||||
PSTNSI14( "PSTN or Network 14" ),
|
||||
PSTNSI15( "PSTN or Network 15" ),
|
||||
REGI( "Registration" ),
|
||||
RESERVED( "Reserved" ),
|
||||
SDMI( "Short Data Message" ),
|
||||
SPARE( "Spare" ),
|
||||
TSCI( "TSC" ),
|
||||
USER( "Individual or Group Ident" ),
|
||||
UNKNOWN( "Unknown" );
|
||||
|
||||
private String mLabel;
|
||||
|
||||
private IdentType( String label )
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public static IdentType fromIdent( int ident )
|
||||
{
|
||||
switch( ident )
|
||||
{
|
||||
case 0:
|
||||
return DUMMYI;
|
||||
case 8101:
|
||||
return PSTNGI;
|
||||
case 8102:
|
||||
return PABXI;
|
||||
case 8103:
|
||||
return DNI;
|
||||
case 8121:
|
||||
return PSTNSI1;
|
||||
case 8122:
|
||||
return PSTNSI2;
|
||||
case 8123:
|
||||
return PSTNSI3;
|
||||
case 8124:
|
||||
return PSTNSI4;
|
||||
case 8125:
|
||||
return PSTNSI5;
|
||||
case 8126:
|
||||
return PSTNSI6;
|
||||
case 8127:
|
||||
return PSTNSI7;
|
||||
case 8128:
|
||||
return PSTNSI8;
|
||||
case 8129:
|
||||
return PSTNSI9;
|
||||
case 8130:
|
||||
return PSTNSI10;
|
||||
case 8131:
|
||||
return PSTNSI11;
|
||||
case 8132:
|
||||
return PSTNSI12;
|
||||
case 8133:
|
||||
return PSTNSI13;
|
||||
case 8134:
|
||||
return PSTNSI14;
|
||||
case 8135:
|
||||
return PSTNSI15;
|
||||
case 8181:
|
||||
case 8182:
|
||||
case 8183:
|
||||
case 8184:
|
||||
return RESERVED;
|
||||
case 8185:
|
||||
return REGI;
|
||||
case 8186:
|
||||
return INCI;
|
||||
case 8187:
|
||||
return DIVERTI;
|
||||
case 8188:
|
||||
return SDMI;
|
||||
case 8189:
|
||||
return IPFIXI;
|
||||
case 8190:
|
||||
return TSCI;
|
||||
case 8191:
|
||||
return ALLI;
|
||||
default:
|
||||
if( 1 <= ident && ident <= 8100 )
|
||||
{
|
||||
return USER;
|
||||
}
|
||||
else if( ( 8104 <= ident && ident <= 8120 ) ||
|
||||
( 8136 <= ident && ident <= 8180 ) )
|
||||
{
|
||||
return SPARE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum SystemDefinition
|
||||
{
|
||||
UNKNOWN( "UNKNOWN" ),
|
||||
ANNOUNCE_CONTROL_CHANNEL( "ANNOUNCE CONTROL CHANNEL" ),
|
||||
WITHDRAW_CONTROL_CHANNEL( "WITHDRAW CONTROL CHANNEL" ),
|
||||
SPECIFY_CALL_MAINTENANCE_PARAMETERS( "CALL MAINT PARAMETERS" ),
|
||||
SPECIFY_REGISTRATION_PARAMETERS( "REGISTRATION PARAMETERS" ),
|
||||
BROADCAST_ADJACENT_SITE_CONTROL_CHANNEL_NUMBER( "NEIGHBOR" ),
|
||||
VOTE_NOW_ADVICE( "VOTE NOW" );
|
||||
|
||||
private String mLabel;
|
||||
|
||||
private SystemDefinition( String label )
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public static SystemDefinition fromNumber( int number )
|
||||
{
|
||||
switch( number )
|
||||
{
|
||||
case 0:
|
||||
return ANNOUNCE_CONTROL_CHANNEL;
|
||||
case 1:
|
||||
return WITHDRAW_CONTROL_CHANNEL;
|
||||
case 2:
|
||||
return SPECIFY_CALL_MAINTENANCE_PARAMETERS;
|
||||
case 3:
|
||||
return SPECIFY_REGISTRATION_PARAMETERS;
|
||||
case 4:
|
||||
return BROADCAST_ADJACENT_SITE_CONTROL_CHANNEL_NUMBER;
|
||||
case 5:
|
||||
return VOTE_NOW_ADVICE;
|
||||
default:
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum MPTMessageType
|
||||
{
|
||||
UNKN( -1, "Unknown" ),
|
||||
GTC( 0, "GTC - Goto Channel" ),
|
||||
ALH( 256, "ALH - Aloha" ),
|
||||
ALHS( 257, "ALHS - Standard Data Excluded" ),
|
||||
ALHD( 258, "ALHD - Simple Calls Excluded" ),
|
||||
ALHE( 259, "ALHE - Emergency Calls Only" ),
|
||||
ALHR( 260, "ALHR - Emergency or Registration" ),
|
||||
ALHX( 261, "ALHX - Registration Excluded" ),
|
||||
ALHF( 262, "ALHF - Fallback Mode" ),
|
||||
|
||||
ACK( 264, "ACK - Acknowledge" ),
|
||||
ACKI( 265, "ACKI - More To Follow" ),
|
||||
ACKQ( 266, "ACKQ - Call Queued" ),
|
||||
ACKX( 267, "ACKX - Message Rejected" ),
|
||||
ACKV( 268, "ACKV - Called Unit Unavailable" ),
|
||||
ACKE( 269, "ACKE - Emergency" ),
|
||||
ACKT( 270, "ACKT - Try On Given Address" ),
|
||||
ACKB( 271, "ACKB - Call Back/Negative Ack" ),
|
||||
|
||||
AHOY( 272, "AHOY - General Availability Check" ),
|
||||
AHYX( 274, "AHYX - Cancel Alert/Waiting Status" ),
|
||||
AHYP( 277, "AHYP - Called Unit Presence Monitoring" ),
|
||||
AHYQ( 278, "AHYQ - Status Message" ),
|
||||
AHYC( 279, "AHYC - Short Data Message" ),
|
||||
|
||||
MARK( 280, "MARK - Control Channel Marker" ),
|
||||
MAINT(281, "MAINT - Call Maintenance Message"),
|
||||
CLEAR(282, "CLEAR - Down From Allocated Channel" ),
|
||||
MOVE( 283, "MOVE - To Specified Channel" ),
|
||||
BCAST(284, "BCAST - System Parameters" );
|
||||
|
||||
/* There are more to fill in here */
|
||||
|
||||
private int mNumber;
|
||||
private String mDescription;
|
||||
|
||||
private MPTMessageType( int number, String description )
|
||||
{
|
||||
mNumber = number;
|
||||
mDescription = description;
|
||||
}
|
||||
|
||||
public int getMessageNumber()
|
||||
{
|
||||
return mNumber;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
public static MPTMessageType fromNumber( int number )
|
||||
{
|
||||
if( number < 256 )
|
||||
{
|
||||
return GTC;
|
||||
}
|
||||
|
||||
switch( number )
|
||||
{
|
||||
case 256:
|
||||
return ALH;
|
||||
case 257:
|
||||
return ALHS;
|
||||
case 258:
|
||||
return ALHD;
|
||||
case 259:
|
||||
return ALHE;
|
||||
case 260:
|
||||
return ALHR;
|
||||
case 261:
|
||||
return ALHX;
|
||||
case 262:
|
||||
return ALHF;
|
||||
case 264:
|
||||
return ACK;
|
||||
case 265:
|
||||
return ACKI;
|
||||
case 266:
|
||||
return ACKQ;
|
||||
case 267:
|
||||
return ACKX;
|
||||
case 268:
|
||||
return ACKV;
|
||||
case 269:
|
||||
return ACKE;
|
||||
case 270:
|
||||
return ACKT;
|
||||
case 271:
|
||||
return ACKB;
|
||||
case 272:
|
||||
return AHOY;
|
||||
case 274:
|
||||
return AHYX;
|
||||
case 277:
|
||||
return AHYP;
|
||||
case 278:
|
||||
return AHYQ;
|
||||
case 279:
|
||||
return AHYC;
|
||||
case 280:
|
||||
return MARK;
|
||||
case 281:
|
||||
return MAINT;
|
||||
case 282:
|
||||
return CLEAR;
|
||||
case 283:
|
||||
return MOVE;
|
||||
case 284:
|
||||
return BCAST;
|
||||
default:
|
||||
return UNKN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
src/decode/mpt1327/MPT1327MessageProcessor.java
Normal file
59
src/decode/mpt1327/MPT1327MessageProcessor.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*******************************************************************************
|
||||
* 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 decode.mpt1327;
|
||||
|
||||
import message.Message;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
|
||||
public class MPT1327MessageProcessor implements Listener<BitSetBuffer>
|
||||
{
|
||||
private Broadcaster<Message> mBroadcaster = new Broadcaster<Message>();
|
||||
|
||||
private AliasList mAliasList;
|
||||
|
||||
public MPT1327MessageProcessor( AliasList list )
|
||||
{
|
||||
mAliasList = list;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mBroadcaster.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( BitSetBuffer buffer )
|
||||
{
|
||||
MPT1327Message message = new MPT1327Message( buffer, mAliasList );
|
||||
|
||||
mBroadcaster.receive( message );
|
||||
}
|
||||
|
||||
public void addMessageListener( Listener<Message> listener )
|
||||
{
|
||||
mBroadcaster.addListener( listener );
|
||||
}
|
||||
|
||||
public void removeMessageListener( Listener<Message> listener )
|
||||
{
|
||||
mBroadcaster.removeListener( listener );
|
||||
}
|
||||
}
|
||||
282
src/decode/mpt1327/MPT1327Panel.java
Normal file
282
src/decode/mpt1327/MPT1327Panel.java
Normal file
@@ -0,0 +1,282 @@
|
||||
/*******************************************************************************
|
||||
* 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 decode.mpt1327;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import settings.ColorSetting;
|
||||
import settings.Setting;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import controller.channel.Channel;
|
||||
import controller.state.ChannelState.ChangedAttribute;
|
||||
import controller.state.ChannelStatePanel;
|
||||
|
||||
public class MPT1327Panel extends ChannelStatePanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocol;
|
||||
private JLabel mSourceLabel;
|
||||
private JLabel mChannelLabel;
|
||||
|
||||
private JLabel mStateLabel;
|
||||
private JLabel mTalkgroup;
|
||||
private JLabel mTalkgroupAlias;
|
||||
|
||||
private JLabel mSiteLabel;
|
||||
private JLabel mSite;
|
||||
private JLabel mSiteAliasLabel;
|
||||
|
||||
private MPT1327ChannelState mState;
|
||||
|
||||
private AliasList mAliasList;
|
||||
|
||||
public MPT1327Panel( Channel channel )
|
||||
{
|
||||
super( channel );
|
||||
mState = (MPT1327ChannelState)channel.getProcessingChain().getChannelState();
|
||||
mState.addListener( this );
|
||||
|
||||
mAliasList = mState.getAliasList();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
mState = null;
|
||||
mAliasList = null;
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
mProtocol = new JLabel( "MPT1327" );
|
||||
mProtocol.setFont( mFontDecoder );
|
||||
mProtocol.setForeground( mColorLabelDecoder );
|
||||
|
||||
mSourceLabel = new JLabel( mChannel.getSourceConfiguration().getDescription() );
|
||||
mSourceLabel.setFont( mFontDetails );
|
||||
mSourceLabel.setForeground( mColorLabelDetails );
|
||||
|
||||
mChannelLabel = new JLabel( mChannel.getChannelDisplayName() );
|
||||
mChannelLabel.setFont( mFontDetails );
|
||||
mChannelLabel.setForeground( mColorLabelDetails );
|
||||
|
||||
mStateLabel = new JLabel( mChannel.getProcessingChain().
|
||||
getChannelState().getState().getDisplayValue() );
|
||||
mStateLabel.setFont( mFontDecoder );
|
||||
mStateLabel.setForeground( mColorLabelDecoder );
|
||||
|
||||
mTalkgroup = new JLabel( mState.getFromTalkgroup() );
|
||||
mTalkgroup.setFont( mFontDecoder );
|
||||
mTalkgroup.setForeground( mColorLabelDecoder );
|
||||
|
||||
mTalkgroupAlias = new JLabel();
|
||||
mTalkgroupAlias.setFont( mFontDecoder );
|
||||
mTalkgroupAlias.setForeground( mColorLabelDecoder );
|
||||
|
||||
Alias alias = getTalkgroupAlias( mState.getFromTalkgroup() );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
mTalkgroupAlias.setText( alias.getName() );
|
||||
mTalkgroupAlias.setIcon( getIcon( alias ) );
|
||||
}
|
||||
|
||||
mSiteLabel = new JLabel( "Site:" );
|
||||
mSiteLabel.setFont( mFontDetails );
|
||||
mSiteLabel.setForeground( mColorLabelDetails );
|
||||
|
||||
mSite = new JLabel( String.valueOf( mState.getSite() ) );
|
||||
mSite.setFont( mFontDecoder );
|
||||
mSite.setForeground( mColorLabelDecoder );
|
||||
|
||||
mSiteAliasLabel = new JLabel();
|
||||
mSiteAliasLabel.setFont( mFontDecoder );
|
||||
mSiteAliasLabel.setForeground( mColorLabelDecoder );
|
||||
|
||||
Alias siteAlias = getSiteAlias( mState.getSite() );
|
||||
|
||||
if( siteAlias != null )
|
||||
{
|
||||
mSiteAliasLabel.setText( siteAlias.getName() );
|
||||
}
|
||||
|
||||
add( mProtocol );
|
||||
add( mSourceLabel );
|
||||
add( mChannelLabel, "wrap" );
|
||||
|
||||
add( mStateLabel );
|
||||
add( mTalkgroup );
|
||||
add( mTalkgroupAlias, "wrap" );
|
||||
|
||||
add( mSiteLabel );
|
||||
add( mSite );
|
||||
add( mSiteAliasLabel, "wrap" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( final ChangedAttribute changedAttribute )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
switch( changedAttribute )
|
||||
{
|
||||
case CHANNEL_STATE:
|
||||
mStateLabel.setText( mState.getState().getDisplayValue() );
|
||||
break;
|
||||
case CHANNEL_SITE_NUMBER:
|
||||
mSite.setText( String.valueOf( mState.getSite() ) );
|
||||
|
||||
Alias siteAlias = getSiteAlias( mState.getSite() );
|
||||
|
||||
if( siteAlias != null )
|
||||
{
|
||||
mSiteAliasLabel.setText( siteAlias.getName() );
|
||||
}
|
||||
repaint();
|
||||
break;
|
||||
case FROM_TALKGROUP:
|
||||
mTalkgroup.setText( mState.getFromTalkgroup() );
|
||||
|
||||
Alias alias = getTalkgroupAlias( mState.getFromTalkgroup() );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
mTalkgroupAlias.setText( alias.getName() );
|
||||
mTalkgroupAlias.setIcon( getIcon( alias ) );
|
||||
}
|
||||
repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
private ImageIcon getIcon( Alias alias )
|
||||
{
|
||||
if( alias != null )
|
||||
{
|
||||
String iconName = alias.getIconName();
|
||||
|
||||
if( iconName != null )
|
||||
{
|
||||
return getSettingsManager().getImageIcon( iconName, 12 );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Alias getSiteAlias( int site )
|
||||
{
|
||||
if( site != 0 && mAliasList != null )
|
||||
{
|
||||
return mAliasList.getSiteID( site );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Alias getTalkgroupAlias( String talkgroup )
|
||||
{
|
||||
if( talkgroup != null && mAliasList != null )
|
||||
{
|
||||
return mAliasList.getTalkgroupAlias( talkgroup );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trafficChannelAdded( Channel traffic )
|
||||
{
|
||||
if( !getTrafficPanels().keySet().contains( traffic ) )
|
||||
{
|
||||
MPT1327TrafficPanel panel =
|
||||
new MPT1327TrafficPanel( traffic );
|
||||
|
||||
getTrafficPanels().put( traffic, panel );
|
||||
|
||||
addPanel( panel );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged( Setting setting )
|
||||
{
|
||||
super.settingChanged( setting );
|
||||
|
||||
if( setting instanceof ColorSetting )
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting)setting;
|
||||
|
||||
switch( colorSetting.getColorSettingName() )
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
if( mProtocol != null )
|
||||
{
|
||||
mProtocol.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
if( mStateLabel != null )
|
||||
{
|
||||
mStateLabel.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
if( mTalkgroup != null )
|
||||
{
|
||||
mTalkgroup.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
if( mTalkgroupAlias != null )
|
||||
{
|
||||
mTalkgroupAlias.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
if( mSite != null )
|
||||
{
|
||||
mSite.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
if( mSiteAliasLabel != null )
|
||||
{
|
||||
mSiteAliasLabel.setForeground( mColorLabelDecoder );
|
||||
}
|
||||
break;
|
||||
case CHANNEL_STATE_LABEL_DETAILS:
|
||||
if( mSourceLabel != null )
|
||||
{
|
||||
mSourceLabel.setForeground( mColorLabelDetails );
|
||||
}
|
||||
if( mChannelLabel != null )
|
||||
{
|
||||
mChannelLabel.setForeground( mColorLabelDetails );
|
||||
}
|
||||
if( mSiteLabel != null )
|
||||
{
|
||||
mSiteLabel.setForeground( mColorLabelDetails );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
258
src/decode/mpt1327/MPT1327TrafficPanel.java
Normal file
258
src/decode/mpt1327/MPT1327TrafficPanel.java
Normal file
@@ -0,0 +1,258 @@
|
||||
/*******************************************************************************
|
||||
* 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 decode.mpt1327;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import settings.ColorSetting;
|
||||
import settings.Setting;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ProcessingChain;
|
||||
import controller.state.ChannelState.ChangedAttribute;
|
||||
import controller.state.ChannelStatePanel;
|
||||
|
||||
public class MPT1327TrafficPanel extends ChannelStatePanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocolLabel;
|
||||
private JLabel mFrequencyLabel;
|
||||
private JLabel mChannelLabel;
|
||||
|
||||
private JLabel mStateLabel;
|
||||
private JLabel mFromTalkgroupLabel;
|
||||
private JLabel mFromTalkgroupAliasLabel;
|
||||
|
||||
private JLabel mToLabel;
|
||||
private JLabel mToTalkgroupLabel;
|
||||
private JLabel mToTalkgroupAliasLabel;
|
||||
|
||||
private AliasList mAliasList;
|
||||
|
||||
public MPT1327TrafficPanel( Channel channel )
|
||||
{
|
||||
super( channel );
|
||||
|
||||
mAliasList = channel.getProcessingChain().getChannelState().getAliasList();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
mAliasList = null;
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
mProtocolLabel = new JLabel( "MPT1327" );
|
||||
mProtocolLabel.setFont( mFontDecoder );
|
||||
mProtocolLabel.setForeground( mColorLabelDecoder );
|
||||
|
||||
mFrequencyLabel = new JLabel( mChannel.getSourceConfiguration().getDescription() );
|
||||
mFrequencyLabel.setFont( mFontDetails );
|
||||
mFrequencyLabel.setForeground( mColorLabelDetails );
|
||||
|
||||
MPT1327ChannelState state =
|
||||
(MPT1327ChannelState)mChannel.getProcessingChain().getChannelState();
|
||||
int channelNumber = state.getChannelNumber();
|
||||
|
||||
mChannelLabel = new JLabel( "Channel " + channelNumber );
|
||||
mChannelLabel.setFont( mFontDetails );
|
||||
mChannelLabel.setForeground( mColorLabelDetails );
|
||||
|
||||
mStateLabel = new JLabel( mChannel.getProcessingChain().
|
||||
getChannelState().getState().getDisplayValue() );
|
||||
mStateLabel.setFont( mFontDecoder );
|
||||
mStateLabel.setForeground( mColorLabelDecoder );
|
||||
|
||||
mFromTalkgroupLabel = new JLabel( state.getFromTalkgroup() );
|
||||
mFromTalkgroupLabel.setFont( mFontDecoder );
|
||||
mFromTalkgroupLabel.setForeground( mColorLabelDecoder );
|
||||
|
||||
mFromTalkgroupAliasLabel = new JLabel();
|
||||
mFromTalkgroupAliasLabel.setFont( mFontDecoder );
|
||||
mFromTalkgroupAliasLabel.setForeground( mColorLabelDecoder );
|
||||
|
||||
if( mAliasList != null )
|
||||
{
|
||||
Alias alias = mAliasList.getMPT1327Alias( state.getFromTalkgroup() );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
mFromTalkgroupAliasLabel.setText( alias.getName() );
|
||||
|
||||
mFromTalkgroupAliasLabel.setIcon( getChannel()
|
||||
.getResourceManager().getSettingsManager()
|
||||
.getImageIcon( alias.getIconName(), 12 ) );
|
||||
}
|
||||
}
|
||||
|
||||
mToLabel = new JLabel( "TO:" );
|
||||
mToLabel.setFont( mFontDetails );
|
||||
mToLabel.setForeground( mColorLabelDetails );
|
||||
|
||||
mToTalkgroupLabel = new JLabel( state.getFromTalkgroup() );
|
||||
mToTalkgroupLabel.setFont( mFontDecoder );
|
||||
mToTalkgroupLabel.setForeground( mColorLabelDecoder );
|
||||
|
||||
mToTalkgroupAliasLabel = new JLabel();
|
||||
mToTalkgroupAliasLabel.setFont( mFontDecoder );
|
||||
mToTalkgroupAliasLabel.setForeground( mColorLabelDecoder );
|
||||
|
||||
if( mAliasList != null )
|
||||
{
|
||||
Alias alias = mAliasList.getMPT1327Alias( state.getFromTalkgroup() );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
mToTalkgroupAliasLabel.setText( alias.getName() );
|
||||
|
||||
mToTalkgroupAliasLabel.setIcon( getChannel()
|
||||
.getResourceManager().getSettingsManager()
|
||||
.getImageIcon( alias.getIconName(), 12 ) );
|
||||
}
|
||||
}
|
||||
|
||||
add( mProtocolLabel );
|
||||
add( mFrequencyLabel );
|
||||
add( mChannelLabel, "wrap" );
|
||||
|
||||
add( mStateLabel );
|
||||
add( mFromTalkgroupLabel );
|
||||
add( mFromTalkgroupAliasLabel, "wrap" );
|
||||
|
||||
add( mToLabel );
|
||||
add( mToTalkgroupLabel );
|
||||
add( mToTalkgroupAliasLabel, "wrap" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( final ChangedAttribute changedAttribute )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
ProcessingChain chain = getChannel().getProcessingChain();
|
||||
|
||||
if( chain != null )
|
||||
{
|
||||
final MPT1327ChannelState state =
|
||||
(MPT1327ChannelState)chain.getChannelState();
|
||||
|
||||
if( state != null )
|
||||
{
|
||||
switch( changedAttribute )
|
||||
{
|
||||
case CHANNEL_STATE:
|
||||
mStateLabel.setText( state.getState().getDisplayValue() );
|
||||
break;
|
||||
case CHANNEL_NUMBER:
|
||||
mChannelLabel.setText( "Channel " + state.getChannelNumber() );
|
||||
break;
|
||||
case FROM_TALKGROUP:
|
||||
String talkgroup = state.getFromTalkgroup();
|
||||
|
||||
mFromTalkgroupLabel.setText( talkgroup );
|
||||
|
||||
if( mAliasList != null )
|
||||
{
|
||||
Alias alias = mAliasList.getMPT1327Alias( talkgroup );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
mFromTalkgroupAliasLabel.setText( alias.getName() );
|
||||
|
||||
String icon = alias.getIconName();
|
||||
|
||||
mFromTalkgroupAliasLabel.setIcon( getChannel()
|
||||
.getResourceManager().getSettingsManager()
|
||||
.getImageIcon( icon, 12 ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TO_TALKGROUP:
|
||||
String toTalkgroup = state.getToTalkgroup();
|
||||
|
||||
mToTalkgroupLabel.setText( toTalkgroup );
|
||||
|
||||
if( mAliasList != null )
|
||||
{
|
||||
Alias alias = mAliasList.getMPT1327Alias( toTalkgroup );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
mToTalkgroupAliasLabel.setText( alias.getName() );
|
||||
|
||||
String icon = alias.getIconName();
|
||||
|
||||
if( icon != null )
|
||||
{
|
||||
mToTalkgroupAliasLabel.setIcon( getChannel()
|
||||
.getResourceManager().getSettingsManager()
|
||||
.getImageIcon( icon, 12 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged( Setting setting )
|
||||
{
|
||||
super.settingChanged( setting );
|
||||
|
||||
if( setting instanceof ColorSetting )
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting)setting;
|
||||
|
||||
switch( colorSetting.getColorSettingName() )
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
mProtocolLabel.setForeground( mColorLabelDecoder );
|
||||
mStateLabel.setForeground( mColorLabelDecoder );
|
||||
mFromTalkgroupLabel.setForeground( mColorLabelDecoder );
|
||||
mFromTalkgroupAliasLabel.setForeground( mColorLabelDecoder );
|
||||
mToTalkgroupLabel.setForeground( mColorLabelDecoder );
|
||||
mToTalkgroupAliasLabel.setForeground( mColorLabelDecoder );
|
||||
break;
|
||||
case CHANNEL_STATE_LABEL_DETAILS:
|
||||
mFrequencyLabel.setForeground( mColorLabelDetails );
|
||||
mChannelLabel.setForeground( mColorLabelDetails );
|
||||
mToLabel.setForeground( mColorLabelDetails );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user