#6 DMR Decoder (#947)

* #6 DMR decoder feature - work in progress

* #6 DMR Decoder.

* #6 DMR Decoder.  Code review updates.

Co-authored-by: Zhenyu Mao <maozhenyu@foxmail.com>
Co-authored-by: Denny <denny@denny-desktop>
This commit is contained in:
Denny Sheirer
2020-10-12 04:57:59 -04:00
committed by GitHub
parent b061db1189
commit 7eec82deee
436 changed files with 36258 additions and 2409 deletions

View File

@@ -27,6 +27,9 @@ package io.github.dsheirer.identifier;
public enum Form
{
ALIAS_LIST,
ARS_DEVICE,
ARS_USER,
ARS_PASSWORD,
CALL_PROGRESS_TONE,
CHANNEL,
CHANNEL_DESCRIPTOR,
@@ -39,9 +42,11 @@ public enum Form
FULLY_QUALIFIED_IDENTIFIER,
IPV4_ADDRESS,
KNOX_TONE,
LOCATION,
LOCATION_REGISTRATION_AREA,
LOJACK,
NEIGHBOR_SITE,
NETWORK,
NETWORK_ACCESS_CODE,
PATCH_GROUP,
RADIO,
@@ -54,6 +59,7 @@ public enum Form
TALKGROUP,
TELEPHONE_NUMBER,
TONE,
UDP_PORT,
UNIT_IDENTIFIER,
UNIT_STATUS,
USER_STATUS,

View File

@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* (Immutable) Collection of identifiers with convenient accessor methods
@@ -36,7 +37,7 @@ import java.util.List;
public class IdentifierCollection
{
private final static Logger mLog = LoggerFactory.getLogger(IdentifierCollection.class);
protected List<Identifier> mIdentifiers = new ArrayList<>();
protected List<Identifier> mIdentifiers = new CopyOnWriteArrayList<>();
protected AliasListConfigurationIdentifier mAliasListConfigurationIdentifier;
private int mTimeslot = 0;

View File

@@ -27,8 +27,9 @@ import io.github.dsheirer.sample.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* Identifier collection with methods for changing or updating managed identifiers
@@ -260,12 +261,11 @@ public class MutableIdentifierCollection extends IdentifierCollection implements
*/
public void clear()
{
Iterator<Identifier> it = mIdentifiers.iterator();
List<Identifier> identifiers = new ArrayList<>();
while(it.hasNext())
for(Identifier identifier: identifiers)
{
notifyRemove(it.next());
it.remove();
remove(identifier);
}
}
@@ -274,18 +274,13 @@ public class MutableIdentifierCollection extends IdentifierCollection implements
*/
public void remove(IdentifierClass identifierClass)
{
Iterator<Identifier> it = mIdentifiers.iterator();
List<Identifier> identifiers = new ArrayList<>(mIdentifiers);
Identifier next = null;
while(it.hasNext())
for(Identifier identifier: identifiers)
{
next = it.next();
if(next.getIdentifierClass() == identifierClass)
if(identifier.getIdentifierClass() == identifierClass)
{
it.remove();
notifyRemove(next);
remove(identifier);
}
}
}
@@ -295,18 +290,13 @@ public class MutableIdentifierCollection extends IdentifierCollection implements
*/
public void remove(Form form)
{
Iterator<Identifier> it = mIdentifiers.iterator();
List<Identifier> identifiers = new ArrayList<>(mIdentifiers);
Identifier next = null;
while(it.hasNext())
for(Identifier identifier: identifiers)
{
next = it.next();
if(next.getForm() == form)
if(identifier.getForm() == form)
{
it.remove();
notifyRemove(next);
remove(identifier);
}
}
}
@@ -316,18 +306,13 @@ public class MutableIdentifierCollection extends IdentifierCollection implements
*/
public void remove(Role role)
{
Iterator<Identifier> it = mIdentifiers.iterator();
List<Identifier> identifiers = new ArrayList<>(mIdentifiers);
Identifier next = null;
while(it.hasNext())
for(Identifier identifier: identifiers)
{
next = it.next();
if(next.getRole() == role)
if(identifier.getRole() == role)
{
it.remove();
notifyRemove(next);
remove(identifier);
}
}
}
@@ -337,18 +322,15 @@ public class MutableIdentifierCollection extends IdentifierCollection implements
*/
public void remove(IdentifierClass identifierClass, Form form, Role role)
{
Iterator<Identifier> it = mIdentifiers.iterator();
List<Identifier> identifiers = new ArrayList<>(mIdentifiers);
Identifier next = null;
while(it.hasNext())
for(Identifier identifier: identifiers)
{
next = it.next();
if(next.getIdentifierClass() == identifierClass && next.getForm() == form && next.getRole() == role)
if(identifier.getIdentifierClass() == identifierClass &&
identifier.getForm() == form &&
identifier.getRole() == role)
{
it.remove();
notifyRemove(next);
remove(identifier);
}
}
}
@@ -358,18 +340,13 @@ public class MutableIdentifierCollection extends IdentifierCollection implements
*/
public void remove(IdentifierClass identifierClass, Role role)
{
Iterator<Identifier> it = mIdentifiers.iterator();
List<Identifier> identifiers = new ArrayList<>(mIdentifiers);
Identifier next = null;
while(it.hasNext())
for(Identifier identifier: identifiers)
{
next = it.next();
if(next.getIdentifierClass() == identifierClass && next.getRole() == role)
if(identifier.getIdentifierClass() == identifierClass && identifier.getRole() == role)
{
it.remove();
notifyRemove(next);
remove(identifier);
}
}
}

View File

@@ -26,18 +26,25 @@ import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.identifier.IdentifierClass;
import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.protocol.Protocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Channel state identifier. Reflects the current state of the channel.
*/
public class ChannelStateIdentifier extends Identifier<State>
{
public static final ChannelStateIdentifier ACTIVE = ChannelStateIdentifier.create(State.ACTIVE);
public static final ChannelStateIdentifier CALL = ChannelStateIdentifier.create(State.CALL);
public static final ChannelStateIdentifier CONTROL = ChannelStateIdentifier.create(State.CONTROL);
public static final ChannelStateIdentifier DATA = ChannelStateIdentifier.create(State.DATA);
public static final ChannelStateIdentifier ENCRYPTED = ChannelStateIdentifier.create(State.ENCRYPTED);
public static final ChannelStateIdentifier FADE = ChannelStateIdentifier.create(State.FADE);
public static final ChannelStateIdentifier IDLE = ChannelStateIdentifier.create(State.IDLE);
public static final ChannelStateIdentifier TEARDOWN = ChannelStateIdentifier.create(State.TEARDOWN);
public static final ChannelStateIdentifier RESET = ChannelStateIdentifier.create(State.RESET);
private final static Logger mLog = LoggerFactory.getLogger(ChannelStateIdentifier.class);
public static final ChannelStateIdentifier ACTIVE = new ChannelStateIdentifier(State.ACTIVE);
public static final ChannelStateIdentifier CALL = new ChannelStateIdentifier(State.CALL);
public static final ChannelStateIdentifier CONTROL = new ChannelStateIdentifier(State.CONTROL);
public static final ChannelStateIdentifier DATA = new ChannelStateIdentifier(State.DATA);
public static final ChannelStateIdentifier ENCRYPTED = new ChannelStateIdentifier(State.ENCRYPTED);
public static final ChannelStateIdentifier FADE = new ChannelStateIdentifier(State.FADE);
public static final ChannelStateIdentifier IDLE = new ChannelStateIdentifier(State.IDLE);
public static final ChannelStateIdentifier TEARDOWN = new ChannelStateIdentifier(State.TEARDOWN);
public static final ChannelStateIdentifier RESET = new ChannelStateIdentifier(State.RESET);
public ChannelStateIdentifier(State value)
{
@@ -53,9 +60,32 @@ public class ChannelStateIdentifier extends Identifier<State>
/**
* Creates a decoder state identifier from the decoder state value
*/
public static ChannelStateIdentifier create(State state)
public static ChannelStateIdentifier get(State state)
{
return new ChannelStateIdentifier(state);
switch(state)
{
case ACTIVE:
return ACTIVE;
case CALL:
return CALL;
case CONTROL:
return CONTROL;
case DATA:
return DATA;
case ENCRYPTED:
return ENCRYPTED;
case FADE:
return FADE;
case IDLE:
return IDLE;
case RESET:
return RESET;
case TEARDOWN:
return TEARDOWN;
default:
mLog.warn("Creating new channel state identifier for unrecognized state [" + state + "]");
return new ChannelStateIdentifier(state);
}
}
@Override

View File

@@ -0,0 +1,41 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.identifier.location;
import io.github.dsheirer.identifier.Form;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.identifier.IdentifierClass;
import io.github.dsheirer.identifier.Role;
/**
* Location (point) identifier
*/
public abstract class LocationIdentifier extends Identifier<Point>
{
/**
* Constructs an instance
* @param value location
* @param role to or from
*/
public LocationIdentifier(Point value, Role role)
{
super(value, IdentifierClass.USER, Form.LOCATION, role);
}
}

View File

@@ -0,0 +1,59 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.identifier.location;
/**
* Geospatial point (location)
*/
public class Point
{
private double mLatitude;
private double mLongitude;
/**
* Constructs an instance
* @param latitude in decimal degrees
* @param longitude in decimal degrees
*/
public Point(double latitude, double longitude)
{
mLatitude = latitude;
mLongitude = longitude;
}
public double getLatitude()
{
return mLatitude;
}
public double getLongitude()
{
return mLongitude;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append(Math.abs(mLatitude)).append(mLatitude >= 0 ? "N " : "S ");
sb.append(Math.abs(mLongitude)).append(mLongitude >= 0 ? "E" : "W");
return sb.toString();
}
}

View File

@@ -0,0 +1,37 @@
/*
* ******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* *****************************************************************************
*/
package io.github.dsheirer.identifier.site;
import io.github.dsheirer.identifier.Form;
import io.github.dsheirer.identifier.IdentifierClass;
import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.identifier.integer.IntegerIdentifier;
/**
* Radio site identifier
*/
public abstract class SiteIdentifier extends IntegerIdentifier
{
public SiteIdentifier(int site)
{
super(site, IdentifierClass.NETWORK, Form.SITE, Role.BROADCAST);
}
}