mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-15 10:07:26 -05:00
#2529 NXDN adds aliasing support for Type-D identifiers and fixes issue in certain NXDN messaing where the TO identifiers are incorrectly tagged. (#2547)
Co-authored-by: denny <dennis.sheirer@gmail.com>
This commit is contained in:
@@ -30,12 +30,16 @@ import io.github.dsheirer.alias.id.legacy.mobileID.Min;
|
|||||||
import io.github.dsheirer.alias.id.legacy.siteID.SiteID;
|
import io.github.dsheirer.alias.id.legacy.siteID.SiteID;
|
||||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||||
import io.github.dsheirer.alias.id.priority.Priority;
|
import io.github.dsheirer.alias.id.priority.Priority;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadio;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadioRange;
|
||||||
import io.github.dsheirer.alias.id.radio.P25FullyQualifiedRadio;
|
import io.github.dsheirer.alias.id.radio.P25FullyQualifiedRadio;
|
||||||
import io.github.dsheirer.alias.id.radio.Radio;
|
import io.github.dsheirer.alias.id.radio.Radio;
|
||||||
import io.github.dsheirer.alias.id.radio.RadioRange;
|
import io.github.dsheirer.alias.id.radio.RadioRange;
|
||||||
import io.github.dsheirer.alias.id.record.Record;
|
import io.github.dsheirer.alias.id.record.Record;
|
||||||
import io.github.dsheirer.alias.id.status.UnitStatusID;
|
import io.github.dsheirer.alias.id.status.UnitStatusID;
|
||||||
import io.github.dsheirer.alias.id.status.UserStatusID;
|
import io.github.dsheirer.alias.id.status.UserStatusID;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroup;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroupRange;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.P25FullyQualifiedTalkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.P25FullyQualifiedTalkgroup;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
||||||
@@ -79,6 +83,31 @@ public class AliasFactory
|
|||||||
Min copyMin = new Min();
|
Min copyMin = new Min();
|
||||||
copyMin.setMin(originalMin.getMin());
|
copyMin.setMin(originalMin.getMin());
|
||||||
return copyMin;
|
return copyMin;
|
||||||
|
case NXDN_TYPE_D_RADIO_ID:
|
||||||
|
NXDNTypeDRadio originalTypeDRadio = (NXDNTypeDRadio)id;
|
||||||
|
NXDNTypeDRadio copyTypeDRadio = new NXDNTypeDRadio(originalTypeDRadio.getHomeRepeater(),
|
||||||
|
originalTypeDRadio.getIdentifier());
|
||||||
|
copyTypeDRadio.setOverlap(originalTypeDRadio.overlapProperty().get());
|
||||||
|
return copyTypeDRadio;
|
||||||
|
case NXDN_TYPE_D_RADIO_ID_RANGE:
|
||||||
|
NXDNTypeDRadioRange originalTypeDRadioRange = (NXDNTypeDRadioRange)id;
|
||||||
|
NXDNTypeDRadioRange copyTypeDRadioRange = new NXDNTypeDRadioRange(originalTypeDRadioRange.getHomeRepeater(),
|
||||||
|
originalTypeDRadioRange.getMinIdentifier(), originalTypeDRadioRange.getMaxIdentifier());
|
||||||
|
copyTypeDRadioRange.setOverlap(originalTypeDRadioRange.overlapProperty().get());
|
||||||
|
return copyTypeDRadioRange;
|
||||||
|
case NXDN_TYPE_D_TALKGROUP:
|
||||||
|
NXDNTypeDTalkgroup originalTypeDTalkgroup = (NXDNTypeDTalkgroup)id;
|
||||||
|
NXDNTypeDTalkgroup copyTypeDTalkgroup = new NXDNTypeDTalkgroup(originalTypeDTalkgroup.getHomeRepeater(),
|
||||||
|
originalTypeDTalkgroup.getIdentifier());
|
||||||
|
copyTypeDTalkgroup.setOverlap(originalTypeDTalkgroup.overlapProperty().get());
|
||||||
|
return copyTypeDTalkgroup;
|
||||||
|
case NXDN_TYPE_D_TALKGROUP_RANGE:
|
||||||
|
NXDNTypeDTalkgroupRange originalTypeDTalkgroupRange = (NXDNTypeDTalkgroupRange)id;
|
||||||
|
NXDNTypeDTalkgroupRange copyTypeDTalkgroupRange = new NXDNTypeDTalkgroupRange(
|
||||||
|
originalTypeDTalkgroupRange.getHomeRepeater(), originalTypeDTalkgroupRange.getMinIdentifier(),
|
||||||
|
originalTypeDTalkgroupRange.getMaxIdentifier());
|
||||||
|
copyTypeDTalkgroupRange.setOverlap(originalTypeDTalkgroupRange.overlapProperty().get());
|
||||||
|
return copyTypeDTalkgroupRange;
|
||||||
case P25_FULLY_QUALIFIED_RADIO_ID:
|
case P25_FULLY_QUALIFIED_RADIO_ID:
|
||||||
P25FullyQualifiedRadio originalP25 = (P25FullyQualifiedRadio) id;
|
P25FullyQualifiedRadio originalP25 = (P25FullyQualifiedRadio) id;
|
||||||
P25FullyQualifiedRadio copyP25 = new P25FullyQualifiedRadio(originalP25.getWacn(),
|
P25FullyQualifiedRadio copyP25 = new P25FullyQualifiedRadio(originalP25.getWacn(),
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ public class AliasList
|
|||||||
switch(id.getType())
|
switch(id.getType())
|
||||||
{
|
{
|
||||||
case TALKGROUP:
|
case TALKGROUP:
|
||||||
|
case NXDN_TYPE_D_TALKGROUP:
|
||||||
Talkgroup talkgroup = (Talkgroup)id;
|
Talkgroup talkgroup = (Talkgroup)id;
|
||||||
|
|
||||||
TalkgroupAliasList talkgroupAliasList = mTalkgroupProtocolMap.get(talkgroup.getProtocol());
|
TalkgroupAliasList talkgroupAliasList = mTalkgroupProtocolMap.get(talkgroup.getProtocol());
|
||||||
@@ -147,6 +148,7 @@ public class AliasList
|
|||||||
talkgroupAliasList.add(talkgroup, alias);
|
talkgroupAliasList.add(talkgroup, alias);
|
||||||
break;
|
break;
|
||||||
case TALKGROUP_RANGE:
|
case TALKGROUP_RANGE:
|
||||||
|
case NXDN_TYPE_D_TALKGROUP_RANGE:
|
||||||
TalkgroupRange talkgroupRange = (TalkgroupRange)id;
|
TalkgroupRange talkgroupRange = (TalkgroupRange)id;
|
||||||
|
|
||||||
TalkgroupAliasList talkgroupRangeAliasList = mTalkgroupProtocolMap.get(talkgroupRange.getProtocol());
|
TalkgroupAliasList talkgroupRangeAliasList = mTalkgroupProtocolMap.get(talkgroupRange.getProtocol());
|
||||||
@@ -186,6 +188,7 @@ public class AliasList
|
|||||||
p25TalkgroupAliasList.add(qualifiedTalkgroup, alias);
|
p25TalkgroupAliasList.add(qualifiedTalkgroup, alias);
|
||||||
break;
|
break;
|
||||||
case RADIO_ID:
|
case RADIO_ID:
|
||||||
|
case NXDN_TYPE_D_RADIO_ID:
|
||||||
Radio radio = (Radio)id;
|
Radio radio = (Radio)id;
|
||||||
|
|
||||||
RadioAliasList radioAliasList = mRadioProtocolMap.get(radio.getProtocol());
|
RadioAliasList radioAliasList = mRadioProtocolMap.get(radio.getProtocol());
|
||||||
@@ -199,6 +202,7 @@ public class AliasList
|
|||||||
radioAliasList.add(radio, alias);
|
radioAliasList.add(radio, alias);
|
||||||
break;
|
break;
|
||||||
case RADIO_ID_RANGE:
|
case RADIO_ID_RANGE:
|
||||||
|
case NXDN_TYPE_D_RADIO_ID_RANGE:
|
||||||
RadioRange radioRange = (RadioRange)id;
|
RadioRange radioRange = (RadioRange)id;
|
||||||
|
|
||||||
RadioAliasList radioRangeAliasList = mRadioProtocolMap.get(radioRange.getProtocol());
|
RadioAliasList radioRangeAliasList = mRadioProtocolMap.get(radioRange.getProtocol());
|
||||||
|
|||||||
@@ -35,12 +35,16 @@ import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
|
|||||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
||||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||||
import io.github.dsheirer.alias.id.priority.Priority;
|
import io.github.dsheirer.alias.id.priority.Priority;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadio;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadioRange;
|
||||||
import io.github.dsheirer.alias.id.radio.P25FullyQualifiedRadio;
|
import io.github.dsheirer.alias.id.radio.P25FullyQualifiedRadio;
|
||||||
import io.github.dsheirer.alias.id.radio.Radio;
|
import io.github.dsheirer.alias.id.radio.Radio;
|
||||||
import io.github.dsheirer.alias.id.radio.RadioRange;
|
import io.github.dsheirer.alias.id.radio.RadioRange;
|
||||||
import io.github.dsheirer.alias.id.record.Record;
|
import io.github.dsheirer.alias.id.record.Record;
|
||||||
import io.github.dsheirer.alias.id.status.UnitStatusID;
|
import io.github.dsheirer.alias.id.status.UnitStatusID;
|
||||||
import io.github.dsheirer.alias.id.status.UserStatusID;
|
import io.github.dsheirer.alias.id.status.UserStatusID;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroup;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroupRange;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.P25FullyQualifiedTalkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.P25FullyQualifiedTalkgroup;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.StreamAsTalkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.StreamAsTalkgroup;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||||
@@ -64,6 +68,10 @@ import javafx.util.Callback;
|
|||||||
@JsonSubTypes.Type(value = Min.class, name = "min"),
|
@JsonSubTypes.Type(value = Min.class, name = "min"),
|
||||||
@JsonSubTypes.Type(value = MPT1327ID.class, name = "mpt1327ID"),
|
@JsonSubTypes.Type(value = MPT1327ID.class, name = "mpt1327ID"),
|
||||||
@JsonSubTypes.Type(value = NonRecordable.class, name = "nonRecordable"),
|
@JsonSubTypes.Type(value = NonRecordable.class, name = "nonRecordable"),
|
||||||
|
@JsonSubTypes.Type(value = NXDNTypeDRadio.class, name = "nxdnTypeDRadio"),
|
||||||
|
@JsonSubTypes.Type(value = NXDNTypeDRadioRange.class, name = "nxdnTypeDRadioRange"),
|
||||||
|
@JsonSubTypes.Type(value = NXDNTypeDTalkgroup.class, name = "nxdnTypeDTalkgroup"),
|
||||||
|
@JsonSubTypes.Type(value = NXDNTypeDTalkgroupRange.class, name = "nxdnTypeDTalkgroupRange"),
|
||||||
@JsonSubTypes.Type(value = P25FullyQualifiedRadio.class, name = "p25FullyQualifiedRadio"),
|
@JsonSubTypes.Type(value = P25FullyQualifiedRadio.class, name = "p25FullyQualifiedRadio"),
|
||||||
@JsonSubTypes.Type(value = P25FullyQualifiedTalkgroup.class, name = "p25FullyQualifiedTalkgroup"),
|
@JsonSubTypes.Type(value = P25FullyQualifiedTalkgroup.class, name = "p25FullyQualifiedTalkgroup"),
|
||||||
@JsonSubTypes.Type(value = Priority.class, name = "priority"),
|
@JsonSubTypes.Type(value = Priority.class, name = "priority"),
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ public enum AliasIDType
|
|||||||
LOJACK("LoJack"),
|
LOJACK("LoJack"),
|
||||||
LTR_NET_UID("LTR-Net UID"),
|
LTR_NET_UID("LTR-Net UID"),
|
||||||
MIN("Passport MIN"),
|
MIN("Passport MIN"),
|
||||||
|
NXDN_TYPE_D_RADIO_ID("NXDN Type-D Radio ID"),
|
||||||
|
NXDN_TYPE_D_RADIO_ID_RANGE("NXDN Type-D Radio ID Range"),
|
||||||
|
NXDN_TYPE_D_TALKGROUP("NXDN Type-D Talkgroup"),
|
||||||
|
NXDN_TYPE_D_TALKGROUP_RANGE("NXDN Type-D Talkgroup Range"),
|
||||||
P25_FULLY_QUALIFIED_RADIO_ID("P25 Fully Qualified Radio ID"),
|
P25_FULLY_QUALIFIED_RADIO_ID("P25 Fully Qualified Radio ID"),
|
||||||
P25_FULLY_QUALIFIED_TALKGROUP("P25 Fully Qualified Talkgroup"),
|
P25_FULLY_QUALIFIED_TALKGROUP("P25 Fully Qualified Talkgroup"),
|
||||||
PRIORITY("Audio Priority"),
|
PRIORITY("Audio Priority"),
|
||||||
@@ -58,6 +62,7 @@ public enum AliasIDType
|
|||||||
|
|
||||||
//Values used by the View-By alias editor
|
//Values used by the View-By alias editor
|
||||||
public static EnumSet<AliasIDType> VIEW_BY_VALUES = EnumSet.of(TALKGROUP, TALKGROUP_RANGE, RADIO_ID, RADIO_ID_RANGE,
|
public static EnumSet<AliasIDType> VIEW_BY_VALUES = EnumSet.of(TALKGROUP, TALKGROUP_RANGE, RADIO_ID, RADIO_ID_RANGE,
|
||||||
|
NXDN_TYPE_D_RADIO_ID, NXDN_TYPE_D_RADIO_ID_RANGE, NXDN_TYPE_D_TALKGROUP, NXDN_TYPE_D_TALKGROUP_RANGE,
|
||||||
P25_FULLY_QUALIFIED_RADIO_ID, P25_FULLY_QUALIFIED_TALKGROUP, UNIT_STATUS, STATUS, TONES);
|
P25_FULLY_QUALIFIED_RADIO_ID, P25_FULLY_QUALIFIED_TALKGROUP, UNIT_STATUS, STATUS, TONES);
|
||||||
|
|
||||||
public String toString()
|
public String toString()
|
||||||
|
|||||||
46
src/main/java/io/github/dsheirer/alias/id/INXDNTypeD.java
Normal file
46
src/main/java/io/github/dsheirer/alias/id/INXDNTypeD.java
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 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.alias.id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D alias identifier composed of a home repeater and a radio or talkgroup identifier value.
|
||||||
|
*/
|
||||||
|
public interface INXDNTypeD
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Home repeater for the identifier
|
||||||
|
*/
|
||||||
|
int getHomeRepeater();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the home repeater for the identifier
|
||||||
|
*/
|
||||||
|
void setHomeRepeater(int homeRepeater);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
int getIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
void setIdentifier(int identifier);
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 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.alias.id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D alias identifier range of radio or talkgroup values that share a common home repeater.
|
||||||
|
*/
|
||||||
|
public interface INXDNTypeDRange
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Home repeater for the range
|
||||||
|
*/
|
||||||
|
int getHomeRepeater();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the home repeater for the range
|
||||||
|
*/
|
||||||
|
void setHomeRepeater(int homeRepeater);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
int getMinIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the minimum radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
void setMinIdentifier(int identifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
int getMaxIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
void setMaxIdentifier(int identifier);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 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.alias.id.radio;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeD;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D radio. The value is the over-the-air 16-bit identifier that combines the home repeater and radio so that
|
||||||
|
* it matches the value of an NXDN Type-D radio identifier.
|
||||||
|
*/
|
||||||
|
public class NXDNTypeDRadio extends Radio implements INXDNTypeD
|
||||||
|
{
|
||||||
|
public NXDNTypeDRadio()
|
||||||
|
{
|
||||||
|
//No-arg JAXB constructor
|
||||||
|
setProtocol(Protocol.NXDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param homeRepeater for the radio
|
||||||
|
* @param radio value, without the home repeater
|
||||||
|
*/
|
||||||
|
public NXDNTypeDRadio(int homeRepeater, int radio)
|
||||||
|
{
|
||||||
|
super(Protocol.NXDN, NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, radio));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AliasIDType getType()
|
||||||
|
{
|
||||||
|
return AliasIDType.NXDN_TYPE_D_RADIO_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getHomeRepeater()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDHomeRepeater(getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHomeRepeater(int homeRepeater)
|
||||||
|
{
|
||||||
|
setValue(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, getIdentifier()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setValue(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Type-D Radio ID:").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getIdentifier(), true));
|
||||||
|
sb.append(" Protocol:").append(getProtocol());
|
||||||
|
|
||||||
|
if(!isValid())
|
||||||
|
{
|
||||||
|
sb.append(" **NOT VALID**");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 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.alias.id.radio;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeDRange;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D radio range for a single home repeater. The min and max values are the over-the-air 16-bit identifiers
|
||||||
|
* that combine the home repeater and radio.
|
||||||
|
*/
|
||||||
|
public class NXDNTypeDRadioRange extends RadioRange implements INXDNTypeDRange
|
||||||
|
{
|
||||||
|
public NXDNTypeDRadioRange()
|
||||||
|
{
|
||||||
|
//No-arg JAXB constructor
|
||||||
|
setProtocol(Protocol.NXDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param homeRepeater for the range
|
||||||
|
* @param minRadio value, without the home repeater
|
||||||
|
* @param maxRadio value, without the home repeater
|
||||||
|
*/
|
||||||
|
public NXDNTypeDRadioRange(int homeRepeater, int minRadio, int maxRadio)
|
||||||
|
{
|
||||||
|
super(Protocol.NXDN, NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, minRadio),
|
||||||
|
NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, maxRadio));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AliasIDType getType()
|
||||||
|
{
|
||||||
|
return AliasIDType.NXDN_TYPE_D_RADIO_ID_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getHomeRepeater()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDHomeRepeater(getMinRadio());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHomeRepeater(int homeRepeater)
|
||||||
|
{
|
||||||
|
int min = getMinIdentifier();
|
||||||
|
int max = getMaxIdentifier();
|
||||||
|
setMinRadio(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, min));
|
||||||
|
setMaxRadio(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getMinIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getMinRadio());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMinIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setMinRadio(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getMaxIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getMaxRadio());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setMaxRadio(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid when the base range is valid and both ends of the range use the same home repeater.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isValid()
|
||||||
|
{
|
||||||
|
return super.isValid() && getHomeRepeater() == NXDNTalkgroupFormatter.getTypeDHomeRepeater(getMaxRadio());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Type-D Radio ID Range:").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getMinIdentifier(), true));
|
||||||
|
sb.append(" to ").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getMaxIdentifier(), true));
|
||||||
|
sb.append(" Protocol:").append(getProtocol());
|
||||||
|
|
||||||
|
if(!isValid())
|
||||||
|
{
|
||||||
|
sb.append(" **NOT VALID**");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 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.alias.id.talkgroup;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeD;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D talkgroup. The value is the over-the-air 16-bit identifier that combines the home repeater and talkgroup
|
||||||
|
* so that it matches the value of an NXDN Type-D talkgroup identifier.
|
||||||
|
*/
|
||||||
|
public class NXDNTypeDTalkgroup extends Talkgroup implements INXDNTypeD
|
||||||
|
{
|
||||||
|
public NXDNTypeDTalkgroup()
|
||||||
|
{
|
||||||
|
//No-arg JAXB constructor
|
||||||
|
setProtocol(Protocol.NXDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param homeRepeater for the talkgroup
|
||||||
|
* @param talkgroup value, without the home repeater
|
||||||
|
*/
|
||||||
|
public NXDNTypeDTalkgroup(int homeRepeater, int talkgroup)
|
||||||
|
{
|
||||||
|
super(Protocol.NXDN, NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, talkgroup));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AliasIDType getType()
|
||||||
|
{
|
||||||
|
return AliasIDType.NXDN_TYPE_D_TALKGROUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getHomeRepeater()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDHomeRepeater(getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHomeRepeater(int homeRepeater)
|
||||||
|
{
|
||||||
|
setValue(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, getIdentifier()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setValue(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Type-D Talkgroup:").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getIdentifier(), true));
|
||||||
|
sb.append(" Protocol:").append(getProtocol());
|
||||||
|
|
||||||
|
if(!isValid())
|
||||||
|
{
|
||||||
|
sb.append(" **NOT VALID**");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 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.alias.id.talkgroup;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeDRange;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D talkgroup range for a single home repeater. The min and max values are the over-the-air 16-bit
|
||||||
|
* identifiers that combine the home repeater and talkgroup.
|
||||||
|
*/
|
||||||
|
public class NXDNTypeDTalkgroupRange extends TalkgroupRange implements INXDNTypeDRange
|
||||||
|
{
|
||||||
|
public NXDNTypeDTalkgroupRange()
|
||||||
|
{
|
||||||
|
//No-arg JAXB constructor
|
||||||
|
setProtocol(Protocol.NXDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param homeRepeater for the range
|
||||||
|
* @param minTalkgroup value, without the home repeater
|
||||||
|
* @param maxTalkgroup value, without the home repeater
|
||||||
|
*/
|
||||||
|
public NXDNTypeDTalkgroupRange(int homeRepeater, int minTalkgroup, int maxTalkgroup)
|
||||||
|
{
|
||||||
|
super(Protocol.NXDN, NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, minTalkgroup),
|
||||||
|
NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, maxTalkgroup));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AliasIDType getType()
|
||||||
|
{
|
||||||
|
return AliasIDType.NXDN_TYPE_D_TALKGROUP_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getHomeRepeater()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDHomeRepeater(getMinTalkgroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHomeRepeater(int homeRepeater)
|
||||||
|
{
|
||||||
|
int min = getMinIdentifier();
|
||||||
|
int max = getMaxIdentifier();
|
||||||
|
setMinTalkgroup(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, min));
|
||||||
|
setMaxTalkgroup(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getMinIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getMinTalkgroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMinIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setMinTalkgroup(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getMaxIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getMaxTalkgroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setMaxTalkgroup(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid when the base range is valid and both ends of the range use the same home repeater.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isValid()
|
||||||
|
{
|
||||||
|
return super.isValid() &&
|
||||||
|
getHomeRepeater() == NXDNTalkgroupFormatter.getTypeDHomeRepeater(getMaxTalkgroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Type-D Talkgroup Range:").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getMinIdentifier(), true));
|
||||||
|
sb.append(" to ").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getMaxIdentifier(), true));
|
||||||
|
sb.append(" Protocol:").append(getProtocol());
|
||||||
|
|
||||||
|
if(!isValid())
|
||||||
|
{
|
||||||
|
sb.append(" **NOT VALID**");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,16 +33,22 @@ import io.github.dsheirer.alias.action.clip.ClipAction;
|
|||||||
import io.github.dsheirer.alias.action.script.ScriptAction;
|
import io.github.dsheirer.alias.action.script.ScriptAction;
|
||||||
import io.github.dsheirer.alias.id.AliasID;
|
import io.github.dsheirer.alias.id.AliasID;
|
||||||
import io.github.dsheirer.alias.id.AliasIDType;
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeD;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeDRange;
|
||||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||||
import io.github.dsheirer.alias.id.dcs.Dcs;
|
import io.github.dsheirer.alias.id.dcs.Dcs;
|
||||||
import io.github.dsheirer.alias.id.esn.Esn;
|
import io.github.dsheirer.alias.id.esn.Esn;
|
||||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadio;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadioRange;
|
||||||
import io.github.dsheirer.alias.id.radio.P25FullyQualifiedRadio;
|
import io.github.dsheirer.alias.id.radio.P25FullyQualifiedRadio;
|
||||||
import io.github.dsheirer.alias.id.radio.Radio;
|
import io.github.dsheirer.alias.id.radio.Radio;
|
||||||
import io.github.dsheirer.alias.id.radio.RadioFormatter;
|
import io.github.dsheirer.alias.id.radio.RadioFormatter;
|
||||||
import io.github.dsheirer.alias.id.radio.RadioRange;
|
import io.github.dsheirer.alias.id.radio.RadioRange;
|
||||||
import io.github.dsheirer.alias.id.status.UnitStatusID;
|
import io.github.dsheirer.alias.id.status.UnitStatusID;
|
||||||
import io.github.dsheirer.alias.id.status.UserStatusID;
|
import io.github.dsheirer.alias.id.status.UserStatusID;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroup;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroupRange;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.P25FullyQualifiedTalkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.P25FullyQualifiedTalkgroup;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.StreamAsTalkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.StreamAsTalkgroup;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||||
@@ -70,6 +76,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
@@ -770,6 +777,12 @@ public class AliasItemEditor extends Editor<Alias>
|
|||||||
nxdnMenu.getItems().add(new AddTalkgroupRangeItem(Protocol.NXDN));
|
nxdnMenu.getItems().add(new AddTalkgroupRangeItem(Protocol.NXDN));
|
||||||
nxdnMenu.getItems().add(new AddRadioIdItem(Protocol.NXDN));
|
nxdnMenu.getItems().add(new AddRadioIdItem(Protocol.NXDN));
|
||||||
nxdnMenu.getItems().add(new AddRadioIdRangeItem(Protocol.NXDN));
|
nxdnMenu.getItems().add(new AddRadioIdRangeItem(Protocol.NXDN));
|
||||||
|
nxdnMenu.getItems().add(new SeparatorMenuItem());
|
||||||
|
nxdnMenu.getItems().add(new AddNXDNTypeDItem("Type-D Talkgroup", NXDNTypeDTalkgroup::new));
|
||||||
|
nxdnMenu.getItems().add(new AddNXDNTypeDItem("Type-D Talkgroup Range", NXDNTypeDTalkgroupRange::new));
|
||||||
|
nxdnMenu.getItems().add(new AddNXDNTypeDItem("Type-D Radio ID", NXDNTypeDRadio::new));
|
||||||
|
nxdnMenu.getItems().add(new AddNXDNTypeDItem("Type-D Radio ID Range", NXDNTypeDRadioRange::new));
|
||||||
|
nxdnMenu.getItems().add(new SeparatorMenuItem());
|
||||||
nxdnMenu.getItems().add(new AddTonesItem("AMBE Audio Tones"));
|
nxdnMenu.getItems().add(new AddTonesItem("AMBE Audio Tones"));
|
||||||
|
|
||||||
Menu passportMenu = new ProtocolMenu(Protocol.PASSPORT);
|
Menu passportMenu = new ProtocolMenu(Protocol.PASSPORT);
|
||||||
@@ -1456,6 +1469,24 @@ public class AliasItemEditor extends Editor<Alias>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menu Item for adding a new NXDN Type-D alias identifier
|
||||||
|
*/
|
||||||
|
public class AddNXDNTypeDItem extends MenuItem
|
||||||
|
{
|
||||||
|
public AddNXDNTypeDItem(String label, Supplier<AliasID> supplier)
|
||||||
|
{
|
||||||
|
super(label);
|
||||||
|
setOnAction(event -> {
|
||||||
|
AliasID aliasID = supplier.get();
|
||||||
|
getIdentifiersList().getItems().add(aliasID);
|
||||||
|
getIdentifiersList().getSelectionModel().select(aliasID);
|
||||||
|
getIdentifiersList().scrollTo(aliasID);
|
||||||
|
modifiedProperty().set(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Menu Item for adding a new protocol-specific Talkgroup alias identifier
|
* Menu Item for adding a new protocol-specific Talkgroup alias identifier
|
||||||
*/
|
*/
|
||||||
@@ -1617,7 +1648,11 @@ public class AliasItemEditor extends Editor<Alias>
|
|||||||
|
|
||||||
if(item != null)
|
if(item != null)
|
||||||
{
|
{
|
||||||
if(item instanceof P25FullyQualifiedTalkgroup fqt)
|
if(item instanceof INXDNTypeD || item instanceof INXDNTypeDRange)
|
||||||
|
{
|
||||||
|
setText(item.overlapProperty().get() ? item + " - Error: Overlap" : item.toString());
|
||||||
|
}
|
||||||
|
else if(item instanceof P25FullyQualifiedTalkgroup fqt)
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("APCO-25 Fully Qualified Talkgroup:").append(fqt.getWacn());
|
sb.append("APCO-25 Fully Qualified Talkgroup:").append(fqt.getWacn());
|
||||||
|
|||||||
@@ -20,6 +20,10 @@
|
|||||||
package io.github.dsheirer.gui.playlist.alias.identifier;
|
package io.github.dsheirer.gui.playlist.alias.identifier;
|
||||||
|
|
||||||
import io.github.dsheirer.alias.id.AliasIDType;
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadio;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadioRange;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroup;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroupRange;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -41,6 +45,14 @@ public class IdentifierEditorFactory
|
|||||||
return new EsnEditor();
|
return new EsnEditor();
|
||||||
case LOJACK:
|
case LOJACK:
|
||||||
return new LojackEditor();
|
return new LojackEditor();
|
||||||
|
case NXDN_TYPE_D_RADIO_ID:
|
||||||
|
return new NXDNTypeDEditor<NXDNTypeDRadio>("Radio");
|
||||||
|
case NXDN_TYPE_D_RADIO_ID_RANGE:
|
||||||
|
return new NXDNTypeDRangeEditor<NXDNTypeDRadioRange>("Radio Range");
|
||||||
|
case NXDN_TYPE_D_TALKGROUP:
|
||||||
|
return new NXDNTypeDEditor<NXDNTypeDTalkgroup>("Talkgroup");
|
||||||
|
case NXDN_TYPE_D_TALKGROUP_RANGE:
|
||||||
|
return new NXDNTypeDRangeEditor<NXDNTypeDTalkgroupRange>("Talkgroup Range");
|
||||||
case P25_FULLY_QUALIFIED_RADIO_ID:
|
case P25_FULLY_QUALIFIED_RADIO_ID:
|
||||||
return new P25FullyQualifiedRadioIdEditor(userPreferences);
|
return new P25FullyQualifiedRadioIdEditor(userPreferences);
|
||||||
case P25_FULLY_QUALIFIED_TALKGROUP:
|
case P25_FULLY_QUALIFIED_TALKGROUP:
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 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.gui.playlist.alias.identifier;
|
||||||
|
|
||||||
|
import io.github.dsheirer.alias.id.AliasID;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeD;
|
||||||
|
import io.github.dsheirer.gui.control.IntegerFormatter;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
|
import javafx.beans.value.ChangeListener;
|
||||||
|
import javafx.geometry.HPos;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.control.TextFormatter;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor for NXDN Type-D radio and talkgroup alias identifiers
|
||||||
|
* @param <T> alias identifier to edit
|
||||||
|
*/
|
||||||
|
public class NXDNTypeDEditor<T extends AliasID & INXDNTypeD> extends IdentifierEditor<T>
|
||||||
|
{
|
||||||
|
private final TextField mHomeRepeaterField = new TextField();
|
||||||
|
private final TextField mIdentifierField = new TextField();
|
||||||
|
private final TextFormatter<Integer> mHomeRepeaterFormatter =
|
||||||
|
new IntegerFormatter(0, NXDNTalkgroupFormatter.TYPE_D_MAX_HOME_REPEATER);
|
||||||
|
private final TextFormatter<Integer> mIdentifierFormatter =
|
||||||
|
new IntegerFormatter(0, NXDNTalkgroupFormatter.TYPE_D_MAX_IDENTIFIER);
|
||||||
|
private final ChangeListener<Integer> mHomeRepeaterListener = (observable, oldValue, newValue) -> {
|
||||||
|
if(getItem() != null)
|
||||||
|
{
|
||||||
|
getItem().setHomeRepeater(newValue != null ? newValue : 0);
|
||||||
|
modifiedProperty().set(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final ChangeListener<Integer> mIdentifierListener = (observable, oldValue, newValue) -> {
|
||||||
|
if(getItem() != null)
|
||||||
|
{
|
||||||
|
getItem().setIdentifier(newValue != null ? newValue : 0);
|
||||||
|
modifiedProperty().set(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param identifierLabel for the identifier field: Radio or Talkgroup
|
||||||
|
*/
|
||||||
|
public NXDNTypeDEditor(String identifierLabel)
|
||||||
|
{
|
||||||
|
mHomeRepeaterField.setTextFormatter(mHomeRepeaterFormatter);
|
||||||
|
mHomeRepeaterField.setTooltip(new Tooltip("Home repeater: 0 - " + NXDNTalkgroupFormatter.TYPE_D_MAX_HOME_REPEATER));
|
||||||
|
mIdentifierField.setTextFormatter(mIdentifierFormatter);
|
||||||
|
mIdentifierField.setTooltip(new Tooltip(identifierLabel + ": 0 - " + NXDNTalkgroupFormatter.TYPE_D_MAX_IDENTIFIER));
|
||||||
|
|
||||||
|
GridPane gridPane = new GridPane();
|
||||||
|
gridPane.setHgap(5);
|
||||||
|
gridPane.setVgap(3);
|
||||||
|
|
||||||
|
gridPane.add(new Label("NXDN Type-D"), 0, 0);
|
||||||
|
|
||||||
|
Label homeRepeaterLabel = new Label("Home Repeater");
|
||||||
|
GridPane.setHalignment(homeRepeaterLabel, HPos.RIGHT);
|
||||||
|
gridPane.add(homeRepeaterLabel, 1, 0);
|
||||||
|
gridPane.add(mHomeRepeaterField, 2, 0);
|
||||||
|
|
||||||
|
Label identifierFieldLabel = new Label(identifierLabel);
|
||||||
|
GridPane.setHalignment(identifierFieldLabel, HPos.RIGHT);
|
||||||
|
gridPane.add(identifierFieldLabel, 3, 0);
|
||||||
|
gridPane.add(mIdentifierField, 4, 0);
|
||||||
|
|
||||||
|
getChildren().add(gridPane);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItem(T item)
|
||||||
|
{
|
||||||
|
//Clear the item and listeners so that loading the field values doesn't change the item
|
||||||
|
mHomeRepeaterFormatter.valueProperty().removeListener(mHomeRepeaterListener);
|
||||||
|
mIdentifierFormatter.valueProperty().removeListener(mIdentifierListener);
|
||||||
|
|
||||||
|
super.setItem(item);
|
||||||
|
|
||||||
|
mHomeRepeaterField.setDisable(item == null);
|
||||||
|
mIdentifierField.setDisable(item == null);
|
||||||
|
mHomeRepeaterFormatter.setValue(item != null ? item.getHomeRepeater() : null);
|
||||||
|
mIdentifierFormatter.setValue(item != null ? item.getIdentifier() : null);
|
||||||
|
|
||||||
|
mHomeRepeaterFormatter.valueProperty().addListener(mHomeRepeaterListener);
|
||||||
|
mIdentifierFormatter.valueProperty().addListener(mIdentifierListener);
|
||||||
|
|
||||||
|
modifiedProperty().set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save()
|
||||||
|
{
|
||||||
|
//no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose()
|
||||||
|
{
|
||||||
|
//no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 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.gui.playlist.alias.identifier;
|
||||||
|
|
||||||
|
import io.github.dsheirer.alias.id.AliasID;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeDRange;
|
||||||
|
import io.github.dsheirer.gui.control.IntegerFormatter;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
|
import javafx.beans.value.ChangeListener;
|
||||||
|
import javafx.geometry.HPos;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.control.TextFormatter;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor for NXDN Type-D radio and talkgroup range alias identifiers
|
||||||
|
* @param <T> alias identifier to edit
|
||||||
|
*/
|
||||||
|
public class NXDNTypeDRangeEditor<T extends AliasID & INXDNTypeDRange> extends IdentifierEditor<T>
|
||||||
|
{
|
||||||
|
private final TextField mHomeRepeaterField = new TextField();
|
||||||
|
private final TextField mMinField = new TextField();
|
||||||
|
private final TextField mMaxField = new TextField();
|
||||||
|
private final TextFormatter<Integer> mHomeRepeaterFormatter =
|
||||||
|
new IntegerFormatter(0, NXDNTalkgroupFormatter.TYPE_D_MAX_HOME_REPEATER);
|
||||||
|
private final TextFormatter<Integer> mMinFormatter =
|
||||||
|
new IntegerFormatter(0, NXDNTalkgroupFormatter.TYPE_D_MAX_IDENTIFIER);
|
||||||
|
private final TextFormatter<Integer> mMaxFormatter =
|
||||||
|
new IntegerFormatter(0, NXDNTalkgroupFormatter.TYPE_D_MAX_IDENTIFIER);
|
||||||
|
private final ChangeListener<Integer> mHomeRepeaterListener = (observable, oldValue, newValue) -> {
|
||||||
|
if(getItem() != null)
|
||||||
|
{
|
||||||
|
getItem().setHomeRepeater(newValue != null ? newValue : 0);
|
||||||
|
modifiedProperty().set(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final ChangeListener<Integer> mMinListener = (observable, oldValue, newValue) -> {
|
||||||
|
if(getItem() != null)
|
||||||
|
{
|
||||||
|
getItem().setMinIdentifier(newValue != null ? newValue : 0);
|
||||||
|
modifiedProperty().set(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final ChangeListener<Integer> mMaxListener = (observable, oldValue, newValue) -> {
|
||||||
|
if(getItem() != null)
|
||||||
|
{
|
||||||
|
getItem().setMaxIdentifier(newValue != null ? newValue : 0);
|
||||||
|
modifiedProperty().set(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param rangeLabel for the range fields: Radio Range or Talkgroup Range
|
||||||
|
*/
|
||||||
|
public NXDNTypeDRangeEditor(String rangeLabel)
|
||||||
|
{
|
||||||
|
String identifierTooltip = rangeLabel + ": 0 - " + NXDNTalkgroupFormatter.TYPE_D_MAX_IDENTIFIER;
|
||||||
|
mHomeRepeaterField.setTextFormatter(mHomeRepeaterFormatter);
|
||||||
|
mHomeRepeaterField.setTooltip(new Tooltip("Home repeater: 0 - " + NXDNTalkgroupFormatter.TYPE_D_MAX_HOME_REPEATER));
|
||||||
|
mMinField.setTextFormatter(mMinFormatter);
|
||||||
|
mMinField.setTooltip(new Tooltip(identifierTooltip));
|
||||||
|
mMaxField.setTextFormatter(mMaxFormatter);
|
||||||
|
mMaxField.setTooltip(new Tooltip(identifierTooltip));
|
||||||
|
|
||||||
|
GridPane gridPane = new GridPane();
|
||||||
|
gridPane.setHgap(5);
|
||||||
|
gridPane.setVgap(3);
|
||||||
|
|
||||||
|
gridPane.add(new Label("NXDN Type-D"), 0, 0);
|
||||||
|
|
||||||
|
Label homeRepeaterLabel = new Label("Home Repeater");
|
||||||
|
GridPane.setHalignment(homeRepeaterLabel, HPos.RIGHT);
|
||||||
|
gridPane.add(homeRepeaterLabel, 1, 0);
|
||||||
|
gridPane.add(mHomeRepeaterField, 2, 0);
|
||||||
|
|
||||||
|
Label rangeFieldLabel = new Label(rangeLabel);
|
||||||
|
GridPane.setHalignment(rangeFieldLabel, HPos.RIGHT);
|
||||||
|
gridPane.add(rangeFieldLabel, 3, 0);
|
||||||
|
gridPane.add(mMinField, 4, 0);
|
||||||
|
gridPane.add(new Label("-"), 5, 0);
|
||||||
|
gridPane.add(mMaxField, 6, 0);
|
||||||
|
|
||||||
|
getChildren().add(gridPane);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItem(T item)
|
||||||
|
{
|
||||||
|
//Clear the item and listeners so that loading the field values doesn't change the item
|
||||||
|
mHomeRepeaterFormatter.valueProperty().removeListener(mHomeRepeaterListener);
|
||||||
|
mMinFormatter.valueProperty().removeListener(mMinListener);
|
||||||
|
mMaxFormatter.valueProperty().removeListener(mMaxListener);
|
||||||
|
|
||||||
|
super.setItem(item);
|
||||||
|
|
||||||
|
mHomeRepeaterField.setDisable(item == null);
|
||||||
|
mMinField.setDisable(item == null);
|
||||||
|
mMaxField.setDisable(item == null);
|
||||||
|
mHomeRepeaterFormatter.setValue(item != null ? item.getHomeRepeater() : null);
|
||||||
|
mMinFormatter.setValue(item != null ? item.getMinIdentifier() : null);
|
||||||
|
mMaxFormatter.setValue(item != null ? item.getMaxIdentifier() : null);
|
||||||
|
|
||||||
|
mHomeRepeaterFormatter.valueProperty().addListener(mHomeRepeaterListener);
|
||||||
|
mMinFormatter.valueProperty().addListener(mMinListener);
|
||||||
|
mMaxFormatter.valueProperty().addListener(mMaxListener);
|
||||||
|
|
||||||
|
modifiedProperty().set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save()
|
||||||
|
{
|
||||||
|
//no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose()
|
||||||
|
{
|
||||||
|
//no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -293,9 +293,9 @@ public class RadioIdRangeEditor extends IdentifierEditor<RadioRange>
|
|||||||
details.add(new RadioIdDetail(Protocol.APCO25, IntegerFormat.HEXADECIMAL, new HexFormatter(0,0xFFFFFF),
|
details.add(new RadioIdDetail(Protocol.APCO25, IntegerFormat.HEXADECIMAL, new HexFormatter(0,0xFFFFFF),
|
||||||
new HexFormatter(0,0xFFFFFF), "Format: 0 - FFFFFF"));
|
new HexFormatter(0,0xFFFFFF), "Format: 0 - FFFFFF"));
|
||||||
details.add(new RadioIdDetail(Protocol.NXDN, IntegerFormat.DECIMAL, new IntegerFormatter(0,0xFFFF),
|
details.add(new RadioIdDetail(Protocol.NXDN, IntegerFormat.DECIMAL, new IntegerFormatter(0,0xFFFF),
|
||||||
new IntegerFormatter(0,0xFFFF),"Format: 0 - 65,535"));
|
new IntegerFormatter(0,0xFFFF),"Format: 1 - 65,535"));
|
||||||
details.add(new RadioIdDetail(Protocol.NXDN, IntegerFormat.HEXADECIMAL, new HexFormatter(0,0xFFFF),
|
details.add(new RadioIdDetail(Protocol.NXDN, IntegerFormat.HEXADECIMAL, new HexFormatter(0,0xFFFF),
|
||||||
new IntegerFormatter(0,0xFFFF),"Format: 0 - FFFF"));
|
new HexFormatter(0,0xFFFF),"Format: 1 - FFFF"));
|
||||||
details.add(new RadioIdDetail(Protocol.PASSPORT, IntegerFormat.DECIMAL, new IntegerFormatter(0,0x7FFFFF),
|
details.add(new RadioIdDetail(Protocol.PASSPORT, IntegerFormat.DECIMAL, new IntegerFormatter(0,0x7FFFFF),
|
||||||
new IntegerFormatter(0,0x7FFFFF), "Format: 0 - 8388607"));
|
new IntegerFormatter(0,0x7FFFFF), "Format: 0 - 8388607"));
|
||||||
details.add(new RadioIdDetail(Protocol.PASSPORT, IntegerFormat.HEXADECIMAL, new HexFormatter(0,0x7FFFFF),
|
details.add(new RadioIdDetail(Protocol.PASSPORT, IntegerFormat.HEXADECIMAL, new HexFormatter(0,0x7FFFFF),
|
||||||
|
|||||||
@@ -292,8 +292,8 @@ public class TalkgroupRangeEditor extends IdentifierEditor<TalkgroupRange>
|
|||||||
List<TalkgroupDetail> details = new ArrayList<>();
|
List<TalkgroupDetail> details = new ArrayList<>();
|
||||||
details.add(new TalkgroupDetail(Protocol.AM, IntegerFormat.DECIMAL, new IntegerFormatter(0,65535),
|
details.add(new TalkgroupDetail(Protocol.AM, IntegerFormat.DECIMAL, new IntegerFormatter(0,65535),
|
||||||
new IntegerFormatter(0,65535), "Format 0 - 65535"));
|
new IntegerFormatter(0,65535), "Format 0 - 65535"));
|
||||||
details.add(new TalkgroupDetail(Protocol.AM, IntegerFormat.HEXADECIMAL, new IntegerFormatter(0,65535),
|
details.add(new TalkgroupDetail(Protocol.AM, IntegerFormat.HEXADECIMAL, new HexFormatter(0,65535),
|
||||||
new IntegerFormatter(0,65535), "Format 0 - FFFF"));
|
new HexFormatter(0,65535), "Format 0 - FFFF"));
|
||||||
details.add(new TalkgroupDetail(Protocol.APCO25, IntegerFormat.DECIMAL, new IntegerFormatter(0,65535),
|
details.add(new TalkgroupDetail(Protocol.APCO25, IntegerFormat.DECIMAL, new IntegerFormatter(0,65535),
|
||||||
new IntegerFormatter(0,65535), "Format: 0 - 65535"));
|
new IntegerFormatter(0,65535), "Format: 0 - 65535"));
|
||||||
details.add(new TalkgroupDetail(Protocol.APCO25, IntegerFormat.HEXADECIMAL, new HexFormatter(0,65535),
|
details.add(new TalkgroupDetail(Protocol.APCO25, IntegerFormat.HEXADECIMAL, new HexFormatter(0,65535),
|
||||||
@@ -316,12 +316,12 @@ public class TalkgroupRangeEditor extends IdentifierEditor<TalkgroupRange>
|
|||||||
"Format: PPP-IIII = Prefix (0-127), Ident (1-8191)"));
|
"Format: PPP-IIII = Prefix (0-127), Ident (1-8191)"));
|
||||||
details.add(new TalkgroupDetail(Protocol.NBFM, IntegerFormat.DECIMAL, new IntegerFormatter(0,65535),
|
details.add(new TalkgroupDetail(Protocol.NBFM, IntegerFormat.DECIMAL, new IntegerFormatter(0,65535),
|
||||||
new IntegerFormatter(0,65535), "Format 0 - 65535"));
|
new IntegerFormatter(0,65535), "Format 0 - 65535"));
|
||||||
details.add(new TalkgroupDetail(Protocol.NBFM, IntegerFormat.HEXADECIMAL, new IntegerFormatter(0,65535),
|
details.add(new TalkgroupDetail(Protocol.NBFM, IntegerFormat.HEXADECIMAL, new HexFormatter(0,65535),
|
||||||
new IntegerFormatter(0,65535), "Format 0 - FFFF"));
|
new HexFormatter(0,65535), "Format 0 - FFFF"));
|
||||||
details.add(new TalkgroupDetail(Protocol.NXDN, IntegerFormat.DECIMAL, new IntegerFormatter(1,0xFFFF),
|
details.add(new TalkgroupDetail(Protocol.NXDN, IntegerFormat.DECIMAL, new IntegerFormatter(1,0xFFFF),
|
||||||
new IntegerFormatter(1,0xFFFF),"Format: 1 - 65,535"));
|
new IntegerFormatter(1,0xFFFF),"Format: 1 - 65,535"));
|
||||||
details.add(new TalkgroupDetail(Protocol.NXDN, IntegerFormat.HEXADECIMAL, new HexFormatter(1,0xFFFF),
|
details.add(new TalkgroupDetail(Protocol.NXDN, IntegerFormat.HEXADECIMAL, new HexFormatter(1,0xFFFF),
|
||||||
new IntegerFormatter(1,0xFFFF),"Format: 1 - FFFF"));
|
new HexFormatter(1,0xFFFF),"Format: 1 - FFFF"));
|
||||||
details.add(new TalkgroupDetail(Protocol.PASSPORT, IntegerFormat.DECIMAL, new IntegerFormatter(0,0xFFFF),
|
details.add(new TalkgroupDetail(Protocol.PASSPORT, IntegerFormat.DECIMAL, new IntegerFormatter(0,0xFFFF),
|
||||||
new IntegerFormatter(0,0xFFFF), "Format: 0 - 65535"));
|
new IntegerFormatter(0,0xFFFF), "Format: 0 - 65535"));
|
||||||
details.add(new TalkgroupDetail(Protocol.PASSPORT, IntegerFormat.HEXADECIMAL, new HexFormatter(0,0xFFFF),
|
details.add(new TalkgroupDetail(Protocol.PASSPORT, IntegerFormat.HEXADECIMAL, new HexFormatter(0,0xFFFF),
|
||||||
|
|||||||
@@ -91,9 +91,9 @@ public abstract class RemoteControl extends CallControl
|
|||||||
}
|
}
|
||||||
else if(getCallControlOption().hasLocationId() && getLocationIDOption().isDestination())
|
else if(getCallControlOption().hasLocationId() && getLocationIDOption().isDestination())
|
||||||
{
|
{
|
||||||
// mDestinationIdentifier = NXDNFullyQualifiedRadioIdentifier.createFrom(getLocationID().getSystem().getValue(),
|
// mDestinationIdentifier = NXDNFullyQualifiedRadioIdentifier.createTo(getLocationID().getSystem().getValue(),
|
||||||
// getMessage().getInt(IDENTIFIER_OCTET_3));
|
// getMessage().getInt(IDENTIFIER_OCTET_5));
|
||||||
mDestinationIdentifier = NXDNRadioIdentifier.createFrom(getMessage().getInt(IDENTIFIER_OCTET_3));
|
mDestinationIdentifier = NXDNRadioIdentifier.createTo(getMessage().getInt(IDENTIFIER_OCTET_5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ public class NXDNTalkgroupFormatter extends AbstractIntegerFormatter
|
|||||||
public static final int TYPE_D_REPEATER_WIDTH = 2;
|
public static final int TYPE_D_REPEATER_WIDTH = 2;
|
||||||
public static final int TYPE_D_VALUE_WIDTH = 4;
|
public static final int TYPE_D_VALUE_WIDTH = 4;
|
||||||
public static final String TYPE_D_SEPARATOR = "-";
|
public static final String TYPE_D_SEPARATOR = "-";
|
||||||
|
public static final int TYPE_D_IDENTIFIER_BIT_WIDTH = 11;
|
||||||
|
public static final int TYPE_D_MAX_HOME_REPEATER = 0x1F;
|
||||||
|
public static final int TYPE_D_MAX_IDENTIFIER = 0x7FF;
|
||||||
public static final int GROUP_DECIMAL_WIDTH = 5;
|
public static final int GROUP_DECIMAL_WIDTH = 5;
|
||||||
public static final int UNIT_DECIMAL_WIDTH = 5;
|
public static final int UNIT_DECIMAL_WIDTH = 5;
|
||||||
public static final int GROUP_HEXADECIMAL_WIDTH = 4;
|
public static final int GROUP_HEXADECIMAL_WIDTH = 4;
|
||||||
@@ -129,6 +132,37 @@ public class NXDNTalkgroupFormatter extends AbstractIntegerFormatter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combines the Type-D home repeater and radio or talkgroup into the over-the-air 16-bit identifier value.
|
||||||
|
* @param homeRepeater for the ID
|
||||||
|
* @param identifier radio or talkgroup value
|
||||||
|
* @return combined value
|
||||||
|
*/
|
||||||
|
public static int toTypeDValue(int homeRepeater, int identifier)
|
||||||
|
{
|
||||||
|
return (homeRepeater & TYPE_D_MAX_HOME_REPEATER) << TYPE_D_IDENTIFIER_BIT_WIDTH | (identifier & TYPE_D_MAX_IDENTIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Home repeater from a combined Type-D identifier value
|
||||||
|
* @param value that combines the home repeater and the radio or talkgroup
|
||||||
|
* @return home repeater
|
||||||
|
*/
|
||||||
|
public static int getTypeDHomeRepeater(int value)
|
||||||
|
{
|
||||||
|
return (value >> TYPE_D_IDENTIFIER_BIT_WIDTH) & TYPE_D_MAX_HOME_REPEATER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Radio or talkgroup from a combined Type-D identifier value
|
||||||
|
* @param value that combines the home repeater and the radio or talkgroup
|
||||||
|
* @return radio or talkgroup, without the home repeater
|
||||||
|
*/
|
||||||
|
public static int getTypeDIdentifier(int value)
|
||||||
|
{
|
||||||
|
return value & TYPE_D_MAX_IDENTIFIER;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a Type-D identifier
|
* Formats a Type-D identifier
|
||||||
* @param homeRepeater for the ID
|
* @param homeRepeater for the ID
|
||||||
|
|||||||
203
src/test/java/io/github/dsheirer/alias/NXDNAliasTest.java
Normal file
203
src/test/java/io/github/dsheirer/alias/NXDNAliasTest.java
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 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.alias;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||||
|
import io.github.dsheirer.alias.id.AliasID;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadio;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadioRange;
|
||||||
|
import io.github.dsheirer.alias.id.radio.Radio;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroup;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroupRange;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||||
|
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||||
|
import io.github.dsheirer.identifier.Identifier;
|
||||||
|
import io.github.dsheirer.identifier.Role;
|
||||||
|
import io.github.dsheirer.module.decode.nxdn.identifier.NXDNRadioIdentifier;
|
||||||
|
import io.github.dsheirer.module.decode.nxdn.identifier.NXDNTalkgroupIdentifier;
|
||||||
|
import io.github.dsheirer.module.decode.nxdn.layer3.NXDNMessageType;
|
||||||
|
import io.github.dsheirer.module.decode.nxdn.layer3.call.RemoteControlRequest;
|
||||||
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotSame;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
public class NXDNAliasTest
|
||||||
|
{
|
||||||
|
private static final int HOME_REPEATER = 3;
|
||||||
|
private static final int RAW_TALKGROUP_03_0123 = 6267;
|
||||||
|
private static final int RAW_RADIO_03_0456 = 6600;
|
||||||
|
|
||||||
|
private static Alias alias(AliasID id, AliasList list)
|
||||||
|
{
|
||||||
|
Alias alias = new Alias();
|
||||||
|
alias.setName(id.toString());
|
||||||
|
alias.addAliasID(id);
|
||||||
|
list.addAlias(alias);
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertAlias(Alias expected, AliasList list, Identifier identifier)
|
||||||
|
{
|
||||||
|
assertEquals(List.of(expected), list.getAliases(identifier), "Alias for " + identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void standardIdentifiersStillMatch()
|
||||||
|
{
|
||||||
|
AliasList list = new AliasList("test");
|
||||||
|
Alias talkgroup = alias(new Talkgroup(Protocol.NXDN, 123), list);
|
||||||
|
Alias radio = alias(new Radio(Protocol.NXDN, 456), list);
|
||||||
|
assertAlias(talkgroup, list, NXDNTalkgroupIdentifier.createTo(123));
|
||||||
|
assertAlias(radio, list, NXDNRadioIdentifier.createFrom(456));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void typeDTalkgroupMatchesDisplayedRepeaterAndTalkgroup()
|
||||||
|
{
|
||||||
|
NXDNTypeDTalkgroup id = new NXDNTypeDTalkgroup(HOME_REPEATER, 123);
|
||||||
|
assertEquals(RAW_TALKGROUP_03_0123, id.getValue());
|
||||||
|
assertEquals(HOME_REPEATER, id.getHomeRepeater());
|
||||||
|
assertEquals(123, id.getIdentifier());
|
||||||
|
assertTrue(id.isValid());
|
||||||
|
|
||||||
|
AliasList list = new AliasList("test");
|
||||||
|
Alias alias = alias(id, list);
|
||||||
|
NXDNTalkgroupIdentifier identifier = NXDNTalkgroupIdentifier.createTypeDTo(RAW_TALKGROUP_03_0123);
|
||||||
|
assertEquals("03-0123", identifier.toString());
|
||||||
|
assertAlias(alias, list, identifier);
|
||||||
|
assertTrue(list.getAliases(NXDNTalkgroupIdentifier.createTypeDTo(RAW_TALKGROUP_03_0123 + 2048)).isEmpty(),
|
||||||
|
"Same talkgroup on another home repeater must not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void typeDRadioMatchesDisplayedRepeaterAndRadio()
|
||||||
|
{
|
||||||
|
AliasList list = new AliasList("test");
|
||||||
|
Alias alias = alias(new NXDNTypeDRadio(HOME_REPEATER, 456), list);
|
||||||
|
assertAlias(alias, list, NXDNRadioIdentifier.createTypeDFrom(RAW_RADIO_03_0456));
|
||||||
|
assertAlias(alias, list, NXDNRadioIdentifier.createTypeDTo(RAW_RADIO_03_0456));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void typeDRangesMatchOnlyTheirHomeRepeater()
|
||||||
|
{
|
||||||
|
AliasList list = new AliasList("test");
|
||||||
|
Alias talkgroups = alias(new NXDNTypeDTalkgroupRange(HOME_REPEATER, 100, 200), list);
|
||||||
|
Alias radios = alias(new NXDNTypeDRadioRange(HOME_REPEATER, 400, 500), list);
|
||||||
|
|
||||||
|
assertAlias(talkgroups, list, NXDNTalkgroupIdentifier.createTypeDTo(RAW_TALKGROUP_03_0123));
|
||||||
|
assertAlias(radios, list, NXDNRadioIdentifier.createTypeDFrom(RAW_RADIO_03_0456));
|
||||||
|
assertTrue(list.getAliases(NXDNTalkgroupIdentifier.createTypeDTo((4 << 11) | 123)).isEmpty());
|
||||||
|
assertTrue(list.getAliases(NXDNRadioIdentifier.createTypeDFrom((4 << 11) | 456)).isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void typeDFieldsCanBeEditedIndependently()
|
||||||
|
{
|
||||||
|
NXDNTypeDTalkgroup talkgroup = new NXDNTypeDTalkgroup();
|
||||||
|
assertEquals(Protocol.NXDN, talkgroup.getProtocol());
|
||||||
|
talkgroup.setIdentifier(123);
|
||||||
|
talkgroup.setHomeRepeater(HOME_REPEATER);
|
||||||
|
assertEquals(RAW_TALKGROUP_03_0123, talkgroup.getValue());
|
||||||
|
|
||||||
|
NXDNTypeDRadioRange range = new NXDNTypeDRadioRange();
|
||||||
|
range.setMinIdentifier(400);
|
||||||
|
range.setMaxIdentifier(500);
|
||||||
|
range.setHomeRepeater(HOME_REPEATER);
|
||||||
|
assertEquals(HOME_REPEATER, range.getHomeRepeater());
|
||||||
|
assertEquals(400, range.getMinIdentifier());
|
||||||
|
assertEquals(500, range.getMaxIdentifier());
|
||||||
|
assertTrue(range.isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void typeDRangeAcrossHomeRepeatersIsNotValid()
|
||||||
|
{
|
||||||
|
NXDNTypeDTalkgroupRange range = new NXDNTypeDTalkgroupRange();
|
||||||
|
range.setMinTalkgroup((3 << 11) | 100);
|
||||||
|
range.setMaxTalkgroup((4 << 11) | 100);
|
||||||
|
assertFalse(range.isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void copyRetainsTypeDIdentifierType()
|
||||||
|
{
|
||||||
|
for(AliasID id : List.of(new NXDNTypeDTalkgroup(HOME_REPEATER, 123), new NXDNTypeDRadio(HOME_REPEATER, 456),
|
||||||
|
new NXDNTypeDTalkgroupRange(HOME_REPEATER, 100, 200), new NXDNTypeDRadioRange(HOME_REPEATER, 400, 500)))
|
||||||
|
{
|
||||||
|
Alias original = new Alias();
|
||||||
|
original.setName("original");
|
||||||
|
original.addAliasID(id);
|
||||||
|
AliasID copy = AliasFactory.copyOf(original).getAliasIdentifiers().getFirst();
|
||||||
|
assertNotSame(id, copy);
|
||||||
|
assertEquals(id.getClass(), copy.getClass());
|
||||||
|
assertEquals(id.toString(), copy.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void typeDIdentifiersRoundTripThroughPlaylistXml() throws Exception
|
||||||
|
{
|
||||||
|
XmlMapper mapper = new XmlMapper();
|
||||||
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
|
||||||
|
for(AliasID id : List.of(new NXDNTypeDTalkgroup(HOME_REPEATER, 123), new NXDNTypeDRadio(HOME_REPEATER, 456),
|
||||||
|
new NXDNTypeDTalkgroupRange(HOME_REPEATER, 100, 200), new NXDNTypeDRadioRange(HOME_REPEATER, 400, 500)))
|
||||||
|
{
|
||||||
|
String xml = mapper.writeValueAsString(id);
|
||||||
|
assertFalse(xml.contains("homeRepeater"), xml);
|
||||||
|
AliasID restored = mapper.readValue(xml, AliasID.class);
|
||||||
|
assertEquals(id.getClass(), restored.getClass(), xml);
|
||||||
|
assertEquals(id.toString(), restored.toString(), xml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void remoteControlDestinationWithLocationIdIsTheDestinationRadio()
|
||||||
|
{
|
||||||
|
int source = 456;
|
||||||
|
int destination = 200;
|
||||||
|
|
||||||
|
//Location option values: 0=COMMON, 1=DESTINATION, 2=SOURCE
|
||||||
|
for(int locationOption = 0; locationOption < 3; locationOption++)
|
||||||
|
{
|
||||||
|
CorrectedBinaryMessage message = new CorrectedBinaryMessage(200);
|
||||||
|
message.load(8, 8, 0x40); //Call control option: has location ID
|
||||||
|
message.load(16, 3, 4); //Destination is a radio
|
||||||
|
message.load(24, 16, source);
|
||||||
|
message.load(40, 16, destination);
|
||||||
|
message.load(72, 2, locationOption);
|
||||||
|
|
||||||
|
RemoteControlRequest request = new RemoteControlRequest(message, 1, NXDNMessageType.CONTROL_OUT_52_CC_REMOTE_CONTROL_REQUEST, 1, null);
|
||||||
|
|
||||||
|
NXDNRadioIdentifier radio = assertInstanceOf(NXDNRadioIdentifier.class, request.getDestination());
|
||||||
|
assertEquals(destination, radio.getValue(), "Location option " + locationOption);
|
||||||
|
assertEquals(Role.TO, radio.getRole(), "Location option " + locationOption);
|
||||||
|
assertEquals(source, request.getSource().getValue(), "Location option " + locationOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user