Updates LoJack message/event function and reply code aliasing.

-Adds new LoJack AliasID allowing user to specify a lojack function and
5-character reply code with wildcards.
-Removes SiteID as an alias option for LoJack.

Valid Alias IDs for LoJack now are:
-LoJack Alias ID: for function and reply code combinations
-ESN ID: for transponder addresses
This commit is contained in:
denny
2016-01-01 09:03:04 -05:00
parent e35b0b277e
commit e41e430e45
9 changed files with 464 additions and 63 deletions

View File

@@ -21,6 +21,7 @@ public enum AliasIDType
{
ESN,
Fleetsync,
LoJack,
LTRNetUID,
MDC1200,
MIN,

View File

@@ -1,6 +1,6 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
* Copyright (C) 2014,2015 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,11 +19,14 @@ package alias;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import module.decode.lj1200.LJ1200Message.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,6 +37,7 @@ import alias.action.script.ScriptAction;
import alias.id.esn.Esn;
import alias.id.fleetsync.FleetsyncID;
import alias.id.fleetsync.StatusID;
import alias.id.lojack.LoJackFunctionAndID;
import alias.id.mdc.MDC1200ID;
import alias.id.mobileID.Min;
import alias.id.mpt1327.MPT1327ID;
@@ -51,6 +55,7 @@ import audio.metadata.MetadataType;
FleetsyncID.class,
Esn.class,
Group.class,
LoJackFunctionAndID.class,
MDC1200ID.class,
Min.class,
MPT1327ID.class,
@@ -77,15 +82,16 @@ public class AliasList implements Comparable<AliasList>
private String mName;
private ArrayList<Group> mGroups = new ArrayList<Group>();
private HashMap<String,Alias> mESN = new HashMap<String,Alias>();
private HashMap<String,Alias> mFleetsync = new HashMap<String,Alias>();
private HashMap<String,Alias> mMDC1200 = new HashMap<String,Alias>();
private HashMap<String,Alias> mMobileID = new HashMap<String,Alias>();
private HashMap<String,Alias> mMPT1327 = new HashMap<String,Alias>();
private HashMap<String, Alias> mSiteID = new HashMap<String,Alias>();
private HashMap<Integer, Alias> mStatus = new HashMap<Integer,Alias>();
private HashMap<String,Alias> mTalkgroup = new HashMap<String,Alias>();
private HashMap<Integer,Alias> mUniqueID = new HashMap<Integer,Alias>();
private Map<String,Alias> mESN = new HashMap<>();
private Map<String,Alias> mFleetsync = new HashMap<>();
private Map<LoJackFunctionAndID,Alias> mLoJack = new HashMap<>();
private Map<String,Alias> mMDC1200 = new HashMap<>();
private Map<String,Alias> mMobileID = new HashMap<>();
private Map<String,Alias> mMPT1327 = new HashMap<>();
private Map<String, Alias> mSiteID = new HashMap<>();
private Map<Integer, Alias> mStatus = new HashMap<>();
private Map<String,Alias> mTalkgroup = new HashMap<>();
private Map<Integer,Alias> mUniqueID = new HashMap<>();
private boolean mESNWildcard = false;
private boolean mMobileIDWildcard = false;
@@ -114,6 +120,7 @@ public class AliasList implements Comparable<AliasList>
//Clear hashmaps
mESN.clear();
mFleetsync.clear();
mLoJack.clear();
mMDC1200.clear();
mMobileID.clear();
mMPT1327.clear();
@@ -157,6 +164,9 @@ public class AliasList implements Comparable<AliasList>
mFleetsync.put( fs.getIdent(), alias );
}
break;
case LoJack:
mLoJack.put( (LoJackFunctionAndID)id, alias );
break;
case MDC1200:
MDC1200ID mdc = (MDC1200ID)id;
@@ -242,6 +252,13 @@ public class AliasList implements Comparable<AliasList>
mTalkgroup.put( tgid.getTalkgroup(), alias );
}
break;
case NonRecordable:
case Priority:
//We don't maintain lookups for these items
break;
default:
mLog.warn( "Unrecognized Alias ID Type:" + id.getType().name() );
break;
}
}
}
@@ -299,8 +316,6 @@ public class AliasList implements Comparable<AliasList>
{
if( esn != null )
{
Alias retVal = null;
if( mESNWildcard )
{
for( String regex: mESN.keySet() )
@@ -325,8 +340,6 @@ public class AliasList implements Comparable<AliasList>
{
if( ident != null )
{
Alias retVal = null;
if( mFleetsyncWildcard )
{
for( String regex: mFleetsync.keySet() )
@@ -346,12 +359,26 @@ public class AliasList implements Comparable<AliasList>
return null;
}
public Alias getLoJackAlias( Function function, String id )
{
if( id != null )
{
for( LoJackFunctionAndID lojack: mLoJack.keySet() )
{
if( lojack.matches( function, id ) )
{
return mLoJack.get( lojack );
}
}
}
return null;
}
public Alias getMDC1200Alias( String ident )
{
if( ident != null )
{
Alias retVal = null;
if( mMDC1200Wildcard )
{
for( String regex: mMDC1200.keySet() )

View File

@@ -40,6 +40,8 @@ import alias.id.fleetsync.FleetsyncID;
import alias.id.fleetsync.FleetsyncIDNode;
import alias.id.fleetsync.StatusID;
import alias.id.fleetsync.StatusIDNode;
import alias.id.lojack.LoJackFunctionAndID;
import alias.id.lojack.LoJackIDNode;
import alias.id.mdc.MDC1200ID;
import alias.id.mdc.MDC1200IDNode;
import alias.id.mobileID.MINNode;
@@ -109,6 +111,10 @@ public class AliasNode extends ConfigurableNode
getModel().addNode( new FleetsyncIDNode( (FleetsyncID)aliasID ),
AliasNode.this, getChildCount() );
break;
case LoJack:
getModel().addNode( new LoJackIDNode( (LoJackFunctionAndID)aliasID ),
AliasNode.this, getChildCount() );
break;
case LTRNetUID:
getModel().addNode( new UniqueIDNode( (UniqueID)aliasID ),
AliasNode.this, getChildCount() );
@@ -226,6 +232,27 @@ public class AliasNode extends ConfigurableNode
} );
addIDMenu.add( addFleetsyncItem );
JMenuItem addLoJackItem = new JMenuItem( "LoJack" );
addLoJackItem.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
LoJackFunctionAndID lj = new LoJackFunctionAndID();
getAlias().addAliasID( lj );
LoJackIDNode node = new LoJackIDNode( lj );
getModel().addNode( node,
AliasNode.this,
AliasNode.this.getChildCount() );
node.show();
}
} );
addIDMenu.add( addLoJackItem );
JMenuItem addMDCItem = new JMenuItem( "MDC-1200" );
addMDCItem.addActionListener( new ActionListener()
{

View File

@@ -0,0 +1,132 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2015 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package alias.id.lojack;
import javax.xml.bind.annotation.XmlAttribute;
import module.decode.lj1200.LJ1200Message;
import module.decode.lj1200.LJ1200Message.Function;
import alias.AliasID;
import alias.AliasIDType;
public class LoJackFunctionAndID extends AliasID
{
private LJ1200Message.Function mFunction = Function.F0_UNKNOWN;
private String mID = "*****";
public LoJackFunctionAndID()
{
}
@XmlAttribute( name="id" )
public String getID()
{
return mID;
}
public void setID( String id )
{
mID = id;
}
@XmlAttribute( name="function" )
public Function getFunction()
{
return mFunction;
}
public void setFunction( Function function )
{
mFunction = function;
}
public String toString()
{
return "LoJack FUNC: " + mFunction.getLabel() + " ID:" + ( mID == null ? "" : mID );
}
/**
* Indicates if the function and id combination match this alias id
*/
public boolean matches( Function function, String id )
{
return mFunction == function &&
mID != null &&
id != null &&
id.matches( mID.replace( "*", ".?" ) );
}
@Override
public boolean matches( AliasID id )
{
boolean retVal = false;
if( mID != null && id instanceof LoJackFunctionAndID )
{
LoJackFunctionAndID otherLojack = (LoJackFunctionAndID)id;
if( otherLojack.getFunction() == mFunction )
{
//Create a pattern - replace * wildcards with regex single-char wildcard
String pattern = mID.replace( "*", ".?" );
retVal = otherLojack.getID().matches( pattern );
}
}
return retVal;
}
@Override
public AliasIDType getType()
{
return AliasIDType.LoJack;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result
+ ( ( mFunction == null ) ? 0 : mFunction.hashCode() );
result = prime * result + ( ( mID == null ) ? 0 : mID.hashCode() );
return result;
}
@Override
public boolean equals( Object obj )
{
if ( this == obj )
return true;
if ( obj == null )
return false;
if ( getClass() != obj.getClass() )
return false;
LoJackFunctionAndID other = (LoJackFunctionAndID) obj;
if ( mFunction != other.mFunction )
return false;
if ( mID == null )
{
if ( other.mID != null )
return false;
} else if ( !mID.equals( other.mID ) )
return false;
return true;
}
}

View File

@@ -0,0 +1,123 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2015 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package alias.id.lojack;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import module.decode.lj1200.LJ1200Message;
import module.decode.lj1200.LJ1200Message.Function;
import net.miginfocom.swing.MigLayout;
import controller.ConfigurableNode;
public class LoJackIDEditor extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private LoJackIDNode mLoJackIDNode;
private JComboBox<LJ1200Message.Function> mFunctionCombo;
private JTextField mTextIdent;
private String mHelpText = "Select a LoJack message function code and enter"
+ " a five character reply code or identifier in the ID field.\n\n"
+ "Wildcard: use an asterisk (*) to wildcard any character in the "
+ "five character reply code (e.g. AB*CD or ***12 or *****)\n\n";
public LoJackIDEditor( LoJackIDNode lojackNode )
{
mLoJackIDNode = lojackNode;
initGUI();
}
private void initGUI()
{
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][grow]" ) );
add( new JLabel( "LoJack Function and ID" ), "span,align center" );
LoJackFunctionAndID lojack = mLoJackIDNode.getLoJackID();
add( new JLabel( "Function:" ) );
mFunctionCombo = new JComboBox<LJ1200Message.Function>( Function.values() );
mFunctionCombo.setSelectedItem( lojack.getFunction() );
add( mFunctionCombo, "grow, wrap" );
add( new JLabel( "ID:" ) );
mTextIdent = new JTextField( lojack.getID() );
add( mTextIdent, "grow, wrap" );
JButton btnSave = new JButton( "Save" );
btnSave.addActionListener( LoJackIDEditor.this );
add( btnSave, "growx,push" );
JButton btnReset = new JButton( "Reset" );
btnReset.addActionListener( LoJackIDEditor.this );
add( btnReset, "growx,push" );
JTextArea helpText = new JTextArea( mHelpText );
helpText.setLineWrap( true );
helpText.setBackground( getBackground() );
add( helpText, "span,grow,push" );
}
@Override
public void actionPerformed( ActionEvent e )
{
String command = e.getActionCommand();
final LoJackFunctionAndID lojack = mLoJackIDNode.getLoJackID();
if( command.contentEquals( "Save" ) )
{
String id = mTextIdent.getText();
if( id != null )
{
lojack.setID( id );
lojack.setFunction( (Function)mFunctionCombo.getSelectedItem() );
((ConfigurableNode)mLoJackIDNode.getParent()).sort();
mLoJackIDNode.save();
mLoJackIDNode.show();
}
else
{
JOptionPane.showMessageDialog( LoJackIDEditor.this, "Please enter an ident" );
}
}
else if( command.contentEquals( "Reset" ) )
{
mFunctionCombo.setSelectedItem( lojack.getFunction() );
mTextIdent.setText( lojack.getID() );
}
mLoJackIDNode.refresh();
}
}

View File

@@ -0,0 +1,86 @@
/*******************************************************************************
* 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 alias.id.lojack;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import alias.AliasIDNode;
import alias.AliasNode;
public class LoJackIDNode extends AliasIDNode
{
private static final long serialVersionUID = 1L;
public LoJackIDNode( LoJackFunctionAndID id )
{
super( id );
}
@Override
public JPanel getEditor()
{
return new LoJackIDEditor( this );
}
public LoJackFunctionAndID getLoJackID()
{
return (LoJackFunctionAndID)getUserObject();
}
public String toString()
{
return getLoJackID().toString();
}
public JPopupMenu getContextMenu()
{
JPopupMenu retVal = new JPopupMenu();
JMenuItem deleteItem = new JMenuItem( "Delete" );
deleteItem.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
int n = JOptionPane.showConfirmDialog( getModel().getTree(),
"Are you sure you want to permanently delete this node?" );
if( n == JOptionPane.YES_OPTION )
{
AliasNode parent = (AliasNode)getParent();
parent.getAlias().removeAliasID( getLoJackID() );
save();
getModel().removeNodeFromParent( LoJackIDNode.this );
}
}
} );
retVal.add( deleteItem );
return retVal;
}
}

View File

@@ -17,6 +17,8 @@
******************************************************************************/
package module.decode.event;
import java.awt.EventQueue;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
@@ -58,7 +60,7 @@ public class CallEventPanel extends JPanel implements ChannelEventListener
}
@Override
public void channelChanged( ChannelEvent event )
public void channelChanged( final ChannelEvent event )
{
if( event.getEvent() == Event.CHANGE_SELECTED &&
event.getChannel().isSelected() )
@@ -67,26 +69,34 @@ public class CallEventPanel extends JPanel implements ChannelEventListener
( mDisplayedChannel != null &&
mDisplayedChannel != event.getChannel() ) )
{
removeAll();
JTable table = new JTable(
event.getChannel().getCallEventModel() );
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
removeAll();
JTable table = new JTable(
event.getChannel().getCallEventModel() );
table.setAutoCreateRowSorter( true );
table.setAutoResizeMode( JTable.AUTO_RESIZE_LAST_COLUMN );
table.getColumnModel().getColumn( CallEventModel.FROM_ALIAS )
.setCellRenderer( mRenderer );
table.setAutoCreateRowSorter( true );
table.setAutoResizeMode( JTable.AUTO_RESIZE_LAST_COLUMN );
table.getColumnModel().getColumn( CallEventModel.FROM_ALIAS )
.setCellRenderer( mRenderer );
table.getColumnModel().getColumn( CallEventModel.TO_ALIAS )
.setCellRenderer( mRenderer );
table.getColumnModel().getColumn( CallEventModel.TO_ALIAS )
.setCellRenderer( mRenderer );
add( new JScrollPane( table ) );
mDisplayedChannel = event.getChannel();
revalidate();
repaint();
}
} );
add( new JScrollPane( table ) );
mDisplayedChannel = event.getChannel();
revalidate();
repaint();
}
}
else if( event.getEvent() == Event.CHANNEL_PROCESSING_STOPPED ||
@@ -96,11 +106,19 @@ public class CallEventPanel extends JPanel implements ChannelEventListener
mDisplayedChannel == event.getChannel() )
{
mDisplayedChannel = null;
removeAll();
add( mEmptyScroller );
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
removeAll();
add( mEmptyScroller );
revalidate();
repaint();
revalidate();
repaint();
}
} );
}
}
}

View File

@@ -87,7 +87,7 @@ public class LJ1200DecoderState extends DecoderState
if( lj.isValid() )
{
setAddress( lj.getAddress() );
setAddressAlias( lj.getAddressAlias() );
setAddressAlias( lj.getTransponderAlias() );
mAddresses.add( mAddress );

View File

@@ -17,7 +17,6 @@
******************************************************************************/
package module.decode.lj1200;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
@@ -61,8 +60,6 @@ public class LJ1200Message extends Message
public static int[] MESSAGE_CRC = { 79,78,77,76,75,74,73,72,71,70,69,68,67,
66,65,64 };
private static SimpleDateFormat mSDF = new SimpleDateFormat( "yyyyMMdd HHmmss" );
private BinaryMessage mMessage;
private AliasList mAliasList;
private CRC mCRC;
@@ -126,7 +123,7 @@ public class LJ1200Message extends Message
return mMessage.getHex( ADDRESS, 7 );
}
public Alias getAddressAlias()
public Alias getTransponderAlias()
{
if( mAliasList != null )
{
@@ -136,21 +133,11 @@ public class LJ1200Message extends Message
return null;
}
public Alias getSiteAndReplyCodeAlias()
public Alias getFunctionAndIDAlias()
{
Function function = getFunction();
if( mAliasList != null )
{
if( function == Function.F1_SITE_ID ||
function == Function.F1_SPEED_UP ||
function == Function.F2_TEST ||
function == Function.F3_DEACTIVATE ||
function == Function.F4_ACTIVATE ||
function == Function.FF_TRACK_PULSE )
{
return mAliasList.getSiteID( getReplyCode() );
}
return mAliasList.getLoJackAlias( getFunction(), getReplyCode() );
}
return null;
@@ -200,7 +187,7 @@ public class LJ1200Message extends Message
sb.append( getReplyCode() );
Alias site = getSiteAndReplyCodeAlias();
Alias site = getFunctionAndIDAlias();
if( site != null )
{
@@ -286,7 +273,7 @@ public class LJ1200Message extends Message
@Override
public Alias getFromIDAlias()
{
return getSiteAndReplyCodeAlias();
return getFunctionAndIDAlias();
}
@Override
@@ -415,18 +402,18 @@ public class LJ1200Message extends Message
{
List<Alias> aliases = new ArrayList<Alias>();
Alias siteAndReply = getSiteAndReplyCodeAlias();
Alias functionAndID = getFunctionAndIDAlias();
if( siteAndReply != null )
if( functionAndID != null )
{
aliases.add( siteAndReply );
aliases.add( functionAndID );
}
Alias address = getAddressAlias();
Alias transponder = getTransponderAlias();
if( address != null )
if( transponder != null )
{
aliases.add( address );
aliases.add( transponder );
}
return aliases;