mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 17:47:32 -05:00
Merge pull request #1646 from DSheirer/1637-dmr-cap-plus-and-max-trunking
#1637 DMR Cap+/CapMax Channel Frequency Map / Trunking Issue
This commit is contained in:
@@ -23,6 +23,7 @@ import io.github.dsheirer.buffer.INativeBufferProvider;
|
|||||||
import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest;
|
import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest;
|
||||||
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
||||||
import io.github.dsheirer.eventbus.MyEventBus;
|
import io.github.dsheirer.eventbus.MyEventBus;
|
||||||
|
import io.github.dsheirer.log.LoggingSuppressor;
|
||||||
import io.github.dsheirer.sample.Broadcaster;
|
import io.github.dsheirer.sample.Broadcaster;
|
||||||
import io.github.dsheirer.sample.Listener;
|
import io.github.dsheirer.sample.Listener;
|
||||||
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
|
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
|
||||||
@@ -65,6 +66,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
public class PolyphaseChannelManager implements ISourceEventProcessor
|
public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||||
{
|
{
|
||||||
private static final DecimalFormat FREQUENCY_FORMAT = new DecimalFormat("0.00000");
|
private static final DecimalFormat FREQUENCY_FORMAT = new DecimalFormat("0.00000");
|
||||||
|
private static final LoggingSuppressor LOGGING_SUPPRESSOR = new LoggingSuppressor(LoggerFactory.getLogger(PolyphaseChannelManager.class));
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(PolyphaseChannelManager.class);
|
private final static Logger mLog = LoggerFactory.getLogger(PolyphaseChannelManager.class);
|
||||||
private static final double MINIMUM_CHANNEL_BANDWIDTH = 25000.0;
|
private static final double MINIMUM_CHANNEL_BANDWIDTH = 25000.0;
|
||||||
private static final double CHANNEL_OVERSAMPLING = 2.0;
|
private static final double CHANNEL_OVERSAMPLING = 2.0;
|
||||||
@@ -203,7 +205,8 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
|||||||
}
|
}
|
||||||
catch(IllegalArgumentException iae)
|
catch(IllegalArgumentException iae)
|
||||||
{
|
{
|
||||||
mLog.debug("Couldn't design final output low pass filter for polyphase channel source");
|
LOGGING_SUPPRESSOR.error(iae.getMessage(), 3, "Couldn't allocate channel. " + iae.getMessage());
|
||||||
|
channelSource = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
private ToggleSwitch mUseCompressedTalkgroupsToggle;
|
private ToggleSwitch mUseCompressedTalkgroupsToggle;
|
||||||
private Spinner<Integer> mTrafficChannelPoolSizeSpinner;
|
private Spinner<Integer> mTrafficChannelPoolSizeSpinner;
|
||||||
private TableView<TimeslotFrequency> mTimeslotFrequencyTable;
|
private TableView<TimeslotFrequency> mTimeslotFrequencyTable;
|
||||||
private IntegerTextField mLogicalSlotNumberField;
|
private IntegerTextField mLogicalChannelNumberField;
|
||||||
private FrequencyField mDownlinkFrequencyField;
|
private FrequencyField mDownlinkFrequencyField;
|
||||||
// private FrequencyField mUplinkFrequencyField;
|
// private FrequencyField mUplinkFrequencyField;
|
||||||
private Button mAddTimeslotFrequencyButton;
|
private Button mAddTimeslotFrequencyButton;
|
||||||
@@ -172,7 +172,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
GridPane.setConstraints(useCompressedTalkgroupsLabel, 7, row);
|
GridPane.setConstraints(useCompressedTalkgroupsLabel, 7, row);
|
||||||
gridPane.getChildren().add(useCompressedTalkgroupsLabel);
|
gridPane.getChildren().add(useCompressedTalkgroupsLabel);
|
||||||
|
|
||||||
Label timeslotTableLabel = new Label("Logical Slot Number (LSN) to Frequency Map. Required for: Connect Plus and Tier-III systems that don't use absolute frequencies");
|
Label timeslotTableLabel = new Label("Logical Channel Number (LCN) to Frequency Map. Required for: Connect Plus and Tier-III systems that don't use absolute frequencies. LSN = Logical Slot Number");
|
||||||
GridPane.setHalignment(timeslotTableLabel, HPos.LEFT);
|
GridPane.setHalignment(timeslotTableLabel, HPos.LEFT);
|
||||||
GridPane.setConstraints(timeslotTableLabel, 0, ++row, 6, 1);
|
GridPane.setConstraints(timeslotTableLabel, 0, ++row, 6, 1);
|
||||||
gridPane.getChildren().add(timeslotTableLabel);
|
gridPane.getChildren().add(timeslotTableLabel);
|
||||||
@@ -194,17 +194,13 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
editorBox.setAlignment(Pos.CENTER_LEFT);
|
editorBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
editorBox.setSpacing(5);
|
editorBox.setSpacing(5);
|
||||||
|
|
||||||
Label lsnLabel = new Label("LSN");
|
Label lcnLabel = new Label("LCN");
|
||||||
editorBox.getChildren().addAll(lsnLabel,getLogicalSlotNumberField());
|
editorBox.getChildren().addAll(lcnLabel, getLogicalChannelNumberField());
|
||||||
|
|
||||||
Label downlinkLabel = new Label("Frequency (MHz)");
|
Label downlinkLabel = new Label("Frequency (MHz)");
|
||||||
downlinkLabel.setPadding(new Insets(0,0,0,5));
|
downlinkLabel.setPadding(new Insets(0,0,0,5));
|
||||||
editorBox.getChildren().addAll(downlinkLabel,getDownlinkFrequencyField());
|
editorBox.getChildren().addAll(downlinkLabel,getDownlinkFrequencyField());
|
||||||
|
|
||||||
// Label uplinkLabel = new Label("Uplink");
|
|
||||||
// uplinkLabel.setPadding(new Insets(0,0,0,5));
|
|
||||||
// editorBox.getChildren().addAll(uplinkLabel,getUplinkFrequencyField());
|
|
||||||
|
|
||||||
GridPane.setConstraints(editorBox, 0, row, 4, 1);
|
GridPane.setConstraints(editorBox, 0, row, 4, 1);
|
||||||
gridPane.getChildren().add(editorBox);
|
gridPane.getChildren().add(editorBox);
|
||||||
|
|
||||||
@@ -287,20 +283,22 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
mTimeslotFrequencyTable = new TableView<>(FXCollections.observableArrayList(TimeslotFrequency.extractor()));
|
mTimeslotFrequencyTable = new TableView<>(FXCollections.observableArrayList(TimeslotFrequency.extractor()));
|
||||||
mTimeslotFrequencyTable.setPrefHeight(100.0);
|
mTimeslotFrequencyTable.setPrefHeight(100.0);
|
||||||
|
|
||||||
TableColumn<TimeslotFrequency,Number> numberColumn = new TableColumn("LSN");
|
TableColumn<TimeslotFrequency,Number> numberColumn = new TableColumn("LCN");
|
||||||
numberColumn.setPrefWidth(70);
|
numberColumn.setPrefWidth(75);
|
||||||
numberColumn.setCellValueFactory(cellData -> cellData.getValue().getNumberProperty());
|
numberColumn.setCellValueFactory(cellData -> cellData.getValue().getNumberProperty());
|
||||||
mTimeslotFrequencyTable.getColumns().addAll(numberColumn);
|
mTimeslotFrequencyTable.getColumns().addAll(numberColumn);
|
||||||
mTimeslotFrequencyTable.getSortOrder().add(numberColumn);
|
mTimeslotFrequencyTable.getSortOrder().add(numberColumn);
|
||||||
|
|
||||||
TableColumn<TimeslotFrequency,Number> downlinkColumn = new TableColumn("Frequency (MHz)");
|
TableColumn<TimeslotFrequency,Number> downlinkColumn = new TableColumn("Frequency (MHz)");
|
||||||
downlinkColumn.setCellValueFactory(cellData -> cellData.getValue().getDownlinkMHz());
|
downlinkColumn.setCellValueFactory(cellData -> cellData.getValue().getDownlinkMHz());
|
||||||
downlinkColumn.setPrefWidth(175);
|
downlinkColumn.setPrefWidth(150);
|
||||||
mTimeslotFrequencyTable.getColumns().addAll(downlinkColumn);
|
mTimeslotFrequencyTable.getColumns().addAll(downlinkColumn);
|
||||||
|
|
||||||
// TableColumn<TimeslotFrequency,Number> uplinkColumn = new TableColumn("Uplink (MHz)");
|
TableColumn<TimeslotFrequency,String> lsnColumn = new TableColumn("IDs (TS1/TS2)");
|
||||||
// uplinkColumn.setCellValueFactory(cellData -> cellData.getValue().getUplinkMHz());
|
lsnColumn.setPrefWidth(225);
|
||||||
// mTimeslotFrequencyTable.getColumns().addAll(uplinkColumn);
|
lsnColumn.setCellValueFactory(new PropertyValueFactory<>("logicalSlotNumbers"));
|
||||||
|
mTimeslotFrequencyTable.getColumns().addAll(lsnColumn);
|
||||||
|
|
||||||
|
|
||||||
mTimeslotFrequencyTable.getSelectionModel().selectedItemProperty()
|
mTimeslotFrequencyTable.getSelectionModel().selectedItemProperty()
|
||||||
.addListener((observable, oldValue, newValue) -> setTimeslot(newValue));
|
.addListener((observable, oldValue, newValue) -> setTimeslot(newValue));
|
||||||
@@ -317,20 +315,20 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
//Preserve the current modified flag state since setting values in the editor will change it.
|
//Preserve the current modified flag state since setting values in the editor will change it.
|
||||||
boolean modified = modifiedProperty().get();
|
boolean modified = modifiedProperty().get();
|
||||||
|
|
||||||
getLogicalSlotNumberField().setDisable(timeslot == null);
|
getLogicalChannelNumberField().setDisable(timeslot == null);
|
||||||
getDownlinkFrequencyField().setDisable(timeslot == null);
|
getDownlinkFrequencyField().setDisable(timeslot == null);
|
||||||
// getUplinkFrequencyField().setDisable(timeslot == null);
|
// getUplinkFrequencyField().setDisable(timeslot == null);
|
||||||
getDeleteTimeslotFrequencyButton().setDisable(timeslot == null);
|
getDeleteTimeslotFrequencyButton().setDisable(timeslot == null);
|
||||||
|
|
||||||
if(timeslot != null)
|
if(timeslot != null)
|
||||||
{
|
{
|
||||||
getLogicalSlotNumberField().set(timeslot.getNumber());
|
getLogicalChannelNumberField().set(timeslot.getNumber());
|
||||||
getDownlinkFrequencyField().set(timeslot.getDownlinkFrequency());
|
getDownlinkFrequencyField().set(timeslot.getDownlinkFrequency());
|
||||||
// getUplinkFrequencyField().set(timeslot.getUplinkFrequency());
|
// getUplinkFrequencyField().set(timeslot.getUplinkFrequency());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
getLogicalSlotNumberField().set(0);
|
getLogicalChannelNumberField().set(0);
|
||||||
getDownlinkFrequencyField().set(0);
|
getDownlinkFrequencyField().set(0);
|
||||||
// getUplinkFrequencyField().set(0);
|
// getUplinkFrequencyField().set(0);
|
||||||
}
|
}
|
||||||
@@ -412,19 +410,19 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
return mDeleteTimeslotFrequencyButton;
|
return mDeleteTimeslotFrequencyButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntegerTextField getLogicalSlotNumberField()
|
private IntegerTextField getLogicalChannelNumberField()
|
||||||
{
|
{
|
||||||
if(mLogicalSlotNumberField == null)
|
if(mLogicalChannelNumberField == null)
|
||||||
{
|
{
|
||||||
mLogicalSlotNumberField = new IntegerTextField();
|
mLogicalChannelNumberField = new IntegerTextField();
|
||||||
mLogicalSlotNumberField.setDisable(true);
|
mLogicalChannelNumberField.setDisable(true);
|
||||||
mLogicalSlotNumberField.setPrefWidth(65);
|
mLogicalChannelNumberField.setPrefWidth(65);
|
||||||
mLogicalSlotNumberField.textProperty().addListener((observable, oldValue, newValue) -> {
|
mLogicalChannelNumberField.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
TimeslotFrequency selected = getTimeslotTable().getSelectionModel().getSelectedItem();
|
TimeslotFrequency selected = getTimeslotTable().getSelectionModel().getSelectedItem();
|
||||||
|
|
||||||
if(selected != null)
|
if(selected != null)
|
||||||
{
|
{
|
||||||
Integer value = mLogicalSlotNumberField.get();
|
Integer value = mLogicalChannelNumberField.get();
|
||||||
|
|
||||||
if(value != null)
|
if(value != null)
|
||||||
{
|
{
|
||||||
@@ -436,7 +434,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return mLogicalSlotNumberField;
|
return mLogicalChannelNumberField;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FrequencyField getDownlinkFrequencyField()
|
private FrequencyField getDownlinkFrequencyField()
|
||||||
@@ -610,8 +608,8 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
getTimeslotTable().setDisable(config == null);
|
getTimeslotTable().setDisable(config == null);
|
||||||
getAddTimeslotFrequencyButton().setDisable(config == null);
|
getAddTimeslotFrequencyButton().setDisable(config == null);
|
||||||
getDeleteTimeslotFrequencyButton().setDisable(true);
|
getDeleteTimeslotFrequencyButton().setDisable(true);
|
||||||
getLogicalSlotNumberField().set(0);
|
getLogicalChannelNumberField().set(0);
|
||||||
getLogicalSlotNumberField().setDisable(true);
|
getLogicalChannelNumberField().setDisable(true);
|
||||||
getDownlinkFrequencyField().set(0);
|
getDownlinkFrequencyField().set(0);
|
||||||
getDownlinkFrequencyField().setDisable(true);
|
getDownlinkFrequencyField().setDisable(true);
|
||||||
// getUplinkFrequencyField().set(0);
|
// getUplinkFrequencyField().set(0);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -41,13 +41,12 @@ import io.github.dsheirer.rrapi.type.Tag;
|
|||||||
import io.github.dsheirer.rrapi.type.Talkgroup;
|
import io.github.dsheirer.rrapi.type.Talkgroup;
|
||||||
import io.github.dsheirer.rrapi.type.Type;
|
import io.github.dsheirer.rrapi.type.Type;
|
||||||
import io.github.dsheirer.rrapi.type.Voice;
|
import io.github.dsheirer.rrapi.type.Voice;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for decoding type, flavor and voice for systems and formatting talkgroups according to user preferences.
|
* Utility class for decoding type, flavor and voice for systems and formatting talkgroups according to user preferences.
|
||||||
@@ -374,16 +373,10 @@ public class RadioReferenceDecoder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int lsn = (lcn - 1) * 2 + 1;
|
TimeslotFrequency timeslotFrequency = new TimeslotFrequency();
|
||||||
TimeslotFrequency timeslot1Frequency = new TimeslotFrequency();
|
timeslotFrequency.setNumber(lcn);
|
||||||
timeslot1Frequency.setNumber(lsn);
|
timeslotFrequency.setDownlinkFrequency((long)(siteFrequency.getFrequency() * 1E6));
|
||||||
timeslot1Frequency.setDownlinkFrequency((long)(siteFrequency.getFrequency() * 1E6));
|
frequencies.add(timeslotFrequency);
|
||||||
frequencies.add(timeslot1Frequency);
|
|
||||||
|
|
||||||
TimeslotFrequency timeslot2Frequency = new TimeslotFrequency();
|
|
||||||
timeslot2Frequency.setNumber(lsn + 1);
|
|
||||||
timeslot2Frequency.setDownlinkFrequency((long)(siteFrequency.getFrequency() * 1E6));
|
|
||||||
frequencies.add(timeslot2Frequency);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return frequencies;
|
return frequencies;
|
||||||
|
|||||||
@@ -90,9 +90,9 @@ import io.github.dsheirer.module.decode.ip.mototrbo.xcmp.XCMPPacket;
|
|||||||
import io.github.dsheirer.protocol.Protocol;
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
import io.github.dsheirer.source.tuner.channel.rotation.AddChannelRotationActiveStateRequest;
|
import io.github.dsheirer.source.tuner.channel.rotation.AddChannelRotationActiveStateRequest;
|
||||||
import io.github.dsheirer.util.PacketUtil;
|
import io.github.dsheirer.util.PacketUtil;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
|
||||||
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -111,7 +111,7 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
private DecodeEvent mCurrentCallEvent;
|
private DecodeEvent mCurrentCallEvent;
|
||||||
private long mCurrentFrequency;
|
private long mCurrentFrequency;
|
||||||
private boolean mIgnoreCRCChecksums;
|
private boolean mIgnoreCRCChecksums;
|
||||||
private Map<Integer,DecodeEvent> mDetectedCallEventsMap = new TreeMap<>();
|
private Map<DMRChannel,DecodeEvent> mDetectedCallEventsMap = new HashMap<>();
|
||||||
private static final AddChannelRotationActiveStateRequest CAPACITY_PLUS_ACTIVE_STATE_REQUEST =
|
private static final AddChannelRotationActiveStateRequest CAPACITY_PLUS_ACTIVE_STATE_REQUEST =
|
||||||
new AddChannelRotationActiveStateRequest(State.ACTIVE);
|
new AddChannelRotationActiveStateRequest(State.ACTIVE);
|
||||||
|
|
||||||
@@ -417,7 +417,7 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DecodeEvent packetEvent = DMRDecodeEvent.builder(DecodeEventType.DATA_PACKET, packet.getTimestamp())
|
DecodeEvent packetEvent = DMRDecodeEvent.builder(DecodeEventType.DATA_PACKET, packet.getTimestamp())
|
||||||
.identifiers(getMergedIdentifierCollection(packet.getIdentifiers()))
|
.identifiers(new IdentifierCollection(packet.getIdentifiers()))
|
||||||
.timeslot(getTimeslot())
|
.timeslot(getTimeslot())
|
||||||
.details(packet.toString())
|
.details(packet.toString())
|
||||||
.build();
|
.build();
|
||||||
@@ -429,7 +429,7 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
if (geoPosition != null) {
|
if (geoPosition != null) {
|
||||||
PlottableDecodeEvent plottableDecodeEvent = PlottableDecodeEvent.plottableBuilder(DecodeEventType.GPS, packet.getTimestamp())
|
PlottableDecodeEvent plottableDecodeEvent = PlottableDecodeEvent.plottableBuilder(DecodeEventType.GPS, packet.getTimestamp())
|
||||||
.channel(getCurrentChannel())
|
.channel(getCurrentChannel())
|
||||||
.identifiers(getMergedIdentifierCollection(packet.getIdentifiers()))
|
.identifiers(new IdentifierCollection(packet.getIdentifiers()))
|
||||||
.protocol(Protocol.LRRP)
|
.protocol(Protocol.LRRP)
|
||||||
.location(geoPosition)
|
.location(geoPosition)
|
||||||
.build();
|
.build();
|
||||||
@@ -735,21 +735,22 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
ChannelGrant dataGrant = (ChannelGrant)csbk;
|
ChannelGrant dataGrant = (ChannelGrant)csbk;
|
||||||
DMRChannel channel = dataGrant.getChannel();
|
DMRChannel channel = dataGrant.getChannel();
|
||||||
|
|
||||||
IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers());
|
|
||||||
|
|
||||||
if(hasTrafficChannelManager())
|
if(hasTrafficChannelManager())
|
||||||
{
|
{
|
||||||
|
IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers());
|
||||||
mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(),
|
mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(),
|
||||||
csbk.getTimestamp(), csbk.isEncrypted());
|
csbk.getTimestamp(), csbk.isEncrypted());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue());
|
DecodeEvent event = mDetectedCallEventsMap.get(channel);
|
||||||
|
|
||||||
if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
|
if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
|
||||||
{
|
{
|
||||||
event = getDecodeEvent(csbk, DecodeEventType.DATA_CALL, channel, mergedIdentifiers);
|
event = getDecodeEvent(csbk, DecodeEventType.DATA_CALL, channel,
|
||||||
mDetectedCallEventsMap.put(channel.getValue(), event);
|
new IdentifierCollection(csbk.getIdentifiers()));
|
||||||
|
mDetectedCallEventsMap.put(channel, event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -768,21 +769,22 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
ChannelGrant tgGrant = (ChannelGrant)csbk;
|
ChannelGrant tgGrant = (ChannelGrant)csbk;
|
||||||
DMRChannel channel = tgGrant.getChannel();
|
DMRChannel channel = tgGrant.getChannel();
|
||||||
|
|
||||||
IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers());
|
|
||||||
|
|
||||||
if(hasTrafficChannelManager())
|
if(hasTrafficChannelManager())
|
||||||
{
|
{
|
||||||
|
IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers());
|
||||||
|
|
||||||
mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers,
|
mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers,
|
||||||
csbk.getOpcode(), csbk.getTimestamp(), csbk.isEncrypted());
|
csbk.getOpcode(), csbk.getTimestamp(), csbk.isEncrypted());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue());
|
DecodeEvent event = mDetectedCallEventsMap.get(channel);
|
||||||
|
|
||||||
if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
|
if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
|
||||||
{
|
{
|
||||||
event = getDecodeEvent(csbk, DecodeEventType.CALL_GROUP, channel, mergedIdentifiers);
|
event = getDecodeEvent(csbk, DecodeEventType.CALL_GROUP, channel,
|
||||||
mDetectedCallEventsMap.put(channel.getValue(), event);
|
new IdentifierCollection(csbk.getIdentifiers()));
|
||||||
|
mDetectedCallEventsMap.put(channel, event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -800,21 +802,23 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
{
|
{
|
||||||
ChannelGrant channelGrant = (ChannelGrant)csbk;
|
ChannelGrant channelGrant = (ChannelGrant)csbk;
|
||||||
DMRChannel channel = channelGrant.getChannel();
|
DMRChannel channel = channelGrant.getChannel();
|
||||||
IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers());
|
|
||||||
|
|
||||||
if(hasTrafficChannelManager())
|
if(hasTrafficChannelManager())
|
||||||
{
|
{
|
||||||
|
IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers());
|
||||||
|
|
||||||
mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers,
|
mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers,
|
||||||
csbk.getOpcode(), csbk.getTimestamp(), csbk.isEncrypted());
|
csbk.getOpcode(), csbk.getTimestamp(), csbk.isEncrypted());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue());
|
DecodeEvent event = mDetectedCallEventsMap.get(channel);
|
||||||
|
|
||||||
if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
|
if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
|
||||||
{
|
{
|
||||||
event = getDecodeEvent(csbk, DecodeEventType.CALL_UNIT_TO_UNIT, channel, mergedIdentifiers);
|
event = getDecodeEvent(csbk, DecodeEventType.CALL_UNIT_TO_UNIT, channel,
|
||||||
mDetectedCallEventsMap.put(channel.getValue(), event);
|
new IdentifierCollection(csbk.getIdentifiers()));
|
||||||
|
mDetectedCallEventsMap.put(channel, event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -845,21 +849,22 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
ConnectPlusDataChannelGrant cpdcg = (ConnectPlusDataChannelGrant)csbk;
|
ConnectPlusDataChannelGrant cpdcg = (ConnectPlusDataChannelGrant)csbk;
|
||||||
DMRChannel channel = cpdcg.getChannel();
|
DMRChannel channel = cpdcg.getChannel();
|
||||||
|
|
||||||
IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers());
|
|
||||||
|
|
||||||
if(hasTrafficChannelManager())
|
if(hasTrafficChannelManager())
|
||||||
{
|
{
|
||||||
|
IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers());
|
||||||
|
|
||||||
mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(),
|
mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(),
|
||||||
csbk.getTimestamp(), csbk.isEncrypted());
|
csbk.getTimestamp(), csbk.isEncrypted());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue());
|
DecodeEvent event = mDetectedCallEventsMap.get(channel);
|
||||||
|
|
||||||
if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
|
if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
|
||||||
{
|
{
|
||||||
event = getDecodeEvent(csbk, DecodeEventType.DATA_CALL, channel, mergedIdentifiers);
|
event = getDecodeEvent(csbk, DecodeEventType.DATA_CALL, channel,
|
||||||
mDetectedCallEventsMap.put(channel.getValue(), event);
|
new IdentifierCollection(csbk.getIdentifiers()));
|
||||||
|
mDetectedCallEventsMap.put(channel, event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -875,7 +880,7 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
case MOTOROLA_CONPLUS_REGISTRATION_REQUEST:
|
case MOTOROLA_CONPLUS_REGISTRATION_REQUEST:
|
||||||
DecodeEvent event = DMRDecodeEvent.builder(DecodeEventType.REQUEST, csbk.getTimestamp())
|
DecodeEvent event = DMRDecodeEvent.builder(DecodeEventType.REQUEST, csbk.getTimestamp())
|
||||||
.details("Registration Request")
|
.details("Registration Request")
|
||||||
.identifiers(getMergedIdentifierCollection(csbk.getIdentifiers()))
|
.identifiers(new IdentifierCollection(csbk.getIdentifiers()))
|
||||||
.timeslot(getTimeslot())
|
.timeslot(getTimeslot())
|
||||||
.build();
|
.build();
|
||||||
broadcast(event);
|
broadcast(event);
|
||||||
@@ -884,7 +889,7 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
case MOTOROLA_CONPLUS_REGISTRATION_RESPONSE:
|
case MOTOROLA_CONPLUS_REGISTRATION_RESPONSE:
|
||||||
DecodeEvent regRespEvent = DMRDecodeEvent.builder(DecodeEventType.RESPONSE, csbk.getTimestamp())
|
DecodeEvent regRespEvent = DMRDecodeEvent.builder(DecodeEventType.RESPONSE, csbk.getTimestamp())
|
||||||
.details("Registration Response")
|
.details("Registration Response")
|
||||||
.identifiers(getMergedIdentifierCollection(csbk.getIdentifiers()))
|
.identifiers(new IdentifierCollection(csbk.getIdentifiers()))
|
||||||
.timeslot(getTimeslot())
|
.timeslot(getTimeslot())
|
||||||
.build();
|
.build();
|
||||||
broadcast(regRespEvent);
|
broadcast(regRespEvent);
|
||||||
@@ -896,21 +901,22 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
ConnectPlusVoiceChannelUser cpvcu = (ConnectPlusVoiceChannelUser)csbk;
|
ConnectPlusVoiceChannelUser cpvcu = (ConnectPlusVoiceChannelUser)csbk;
|
||||||
DMRChannel channel = cpvcu.getChannel();
|
DMRChannel channel = cpvcu.getChannel();
|
||||||
|
|
||||||
IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers());
|
|
||||||
|
|
||||||
if(hasTrafficChannelManager())
|
if(hasTrafficChannelManager())
|
||||||
{
|
{
|
||||||
|
IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers());
|
||||||
|
|
||||||
mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(),
|
mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(),
|
||||||
csbk.getTimestamp(), csbk.isEncrypted());
|
csbk.getTimestamp(), csbk.isEncrypted());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DecodeEvent detectedEvent = mDetectedCallEventsMap.get(channel.getValue());
|
DecodeEvent detectedEvent = mDetectedCallEventsMap.get(channel);
|
||||||
|
|
||||||
if(isStale(detectedEvent, csbk.getTimestamp(), csbk.getIdentifiers()))
|
if(isStale(detectedEvent, csbk.getTimestamp(), csbk.getIdentifiers()))
|
||||||
{
|
{
|
||||||
detectedEvent = getDecodeEvent(csbk, DecodeEventType.CALL_GROUP, channel, mergedIdentifiers);
|
detectedEvent = getDecodeEvent(csbk, DecodeEventType.CALL_GROUP, channel,
|
||||||
mDetectedCallEventsMap.put(channel.getValue(), detectedEvent);
|
new IdentifierCollection(csbk.getIdentifiers()));
|
||||||
|
mDetectedCallEventsMap.put(channel, detectedEvent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -926,7 +932,7 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
case MOTOROLA_CONPLUS_TALKGROUP_AFFILIATION:
|
case MOTOROLA_CONPLUS_TALKGROUP_AFFILIATION:
|
||||||
DecodeEvent affiliateEvent = DMRDecodeEvent.builder(DecodeEventType.AFFILIATE, csbk.getTimestamp())
|
DecodeEvent affiliateEvent = DMRDecodeEvent.builder(DecodeEventType.AFFILIATE, csbk.getTimestamp())
|
||||||
.details("TALKGROUP AFFILIATION")
|
.details("TALKGROUP AFFILIATION")
|
||||||
.identifiers(getMergedIdentifierCollection(csbk.getIdentifiers()))
|
.identifiers(new IdentifierCollection(csbk.getIdentifiers()))
|
||||||
.timeslot(getTimeslot())
|
.timeslot(getTimeslot())
|
||||||
.build();
|
.build();
|
||||||
broadcast(affiliateEvent);
|
broadcast(affiliateEvent);
|
||||||
@@ -939,18 +945,18 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DecodeEvent getDecodeEvent(CSBKMessage csbk, DecodeEventType decodeEventType, DMRChannel channel,
|
private DecodeEvent getDecodeEvent(CSBKMessage csbk, DecodeEventType decodeEventType, DMRChannel channel,
|
||||||
IdentifierCollection mergedIdentifiers) {
|
IdentifierCollection identifierCollection) {
|
||||||
return DMRDecodeEvent.builder(decodeEventType, csbk.getTimestamp())
|
return DMRDecodeEvent.builder(decodeEventType, csbk.getTimestamp())
|
||||||
.channel(channel)
|
.channel(channel)
|
||||||
.details(csbk.getOpcode().getLabel())
|
.details(csbk.getOpcode().getLabel())
|
||||||
.identifiers(mergedIdentifiers)
|
.identifiers(identifierCollection)
|
||||||
.timeslot(getTimeslot())
|
.timeslot(getTimeslot())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DecodeEvent getDecodeEvent(CSBKMessage csbk, DecodeEventType decodeEventType, String details) {
|
private DecodeEvent getDecodeEvent(CSBKMessage csbk, DecodeEventType decodeEventType, String details) {
|
||||||
return DMRDecodeEvent.builder(decodeEventType, csbk.getTimestamp())
|
return DMRDecodeEvent.builder(decodeEventType, csbk.getTimestamp())
|
||||||
.identifiers(getMergedIdentifierCollection(csbk.getIdentifiers()))
|
.identifiers(new IdentifierCollection(csbk.getIdentifiers()))
|
||||||
.timeslot(getTimeslot())
|
.timeslot(getTimeslot())
|
||||||
.details(details)
|
.details(details)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -127,19 +127,19 @@ public class DMRMessageProcessor implements Listener<IMessage>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Enrich messages that carry DMR Logical Slot Number channels with LCN to frequency mappings
|
//Enrich messages that carry DMR Logical Channel Numbers with LCN to frequency mappings
|
||||||
if(message instanceof ITimeslotFrequencyReceiver)
|
if(message instanceof ITimeslotFrequencyReceiver)
|
||||||
{
|
{
|
||||||
ITimeslotFrequencyReceiver receiver = (ITimeslotFrequencyReceiver)message;
|
ITimeslotFrequencyReceiver receiver = (ITimeslotFrequencyReceiver)message;
|
||||||
int[] lsns = receiver.getLogicalSlotNumbers();
|
int[] lcns = receiver.getLogicalChannelNumbers();
|
||||||
|
|
||||||
List<TimeslotFrequency> timeslotFrequencies = new ArrayList<>();
|
List<TimeslotFrequency> timeslotFrequencies = new ArrayList<>();
|
||||||
|
|
||||||
for(int lsn: lsns)
|
for(int lcn: lcns)
|
||||||
{
|
{
|
||||||
if(mTimeslotFrequencyMap.containsKey(lsn))
|
if(mTimeslotFrequencyMap.containsKey(lcn))
|
||||||
{
|
{
|
||||||
timeslotFrequencies.add(mTimeslotFrequencyMap.get(lsn));
|
timeslotFrequencies.add(mTimeslotFrequencyMap.get(lcn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* * ******************************************************************************
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
* it under the terms of the GNU General Public License as published by
|
||||||
* *
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
* (at your option) any later version.
|
||||||
* * 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/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
*
|
||||||
|
* 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.module.decode.dmr;
|
package io.github.dsheirer.module.decode.dmr;
|
||||||
@@ -41,14 +38,13 @@ import io.github.dsheirer.module.decode.dmr.message.data.lc.shorty.ConnectPlusCo
|
|||||||
import io.github.dsheirer.module.decode.dmr.message.data.lc.shorty.ConnectPlusTrafficChannel;
|
import io.github.dsheirer.module.decode.dmr.message.data.lc.shorty.ConnectPlusTrafficChannel;
|
||||||
import io.github.dsheirer.module.decode.dmr.message.type.Model;
|
import io.github.dsheirer.module.decode.dmr.message.type.Model;
|
||||||
import io.github.dsheirer.module.decode.dmr.message.type.SystemIdentityCode;
|
import io.github.dsheirer.module.decode.dmr.message.type.SystemIdentityCode;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks the network configuration details of a DMR network from the broadcast messages
|
* Tracks the network configuration details of a DMR network from the broadcast messages
|
||||||
@@ -250,7 +246,7 @@ public class DMRNetworkConfigurationMonitor
|
|||||||
ConnectPlusNeighborReport cpnr = (ConnectPlusNeighborReport)csbk;
|
ConnectPlusNeighborReport cpnr = (ConnectPlusNeighborReport)csbk;
|
||||||
mNeighborSites.addAll(cpnr.getNeighbors());
|
mNeighborSites.addAll(cpnr.getNeighbors());
|
||||||
}
|
}
|
||||||
if(mBrand == null)
|
if(mBrand == null || mBrand != BRAND_MOTOROLA_CONNECT_PLUS)
|
||||||
{
|
{
|
||||||
mBrand = BRAND_MOTOROLA_CONNECT_PLUS;
|
mBrand = BRAND_MOTOROLA_CONNECT_PLUS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I
|
|||||||
private List<Channel> mManagedTrafficChannels;
|
private List<Channel> mManagedTrafficChannels;
|
||||||
|
|
||||||
private Map<Long,Channel> mAllocatedTrafficChannelFrequencyMap = new ConcurrentHashMap<>();
|
private Map<Long,Channel> mAllocatedTrafficChannelFrequencyMap = new ConcurrentHashMap<>();
|
||||||
private Map<Integer,DMRChannelGrantEvent> mLSNGrantEventMap = new ConcurrentHashMap<>();
|
private Map<DMRChannel,DMRChannelGrantEvent> mChannelGrantEventMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private Listener<ChannelEvent> mChannelEventListener;
|
private Listener<ChannelEvent> mChannelEventListener;
|
||||||
private Listener<IDecodeEvent> mDecodeEventListener;
|
private Listener<IDecodeEvent> mDecodeEventListener;
|
||||||
@@ -322,9 +322,7 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I
|
|||||||
public void processChannelGrant(DMRChannel channel, IdentifierCollection identifierCollection,
|
public void processChannelGrant(DMRChannel channel, IdentifierCollection identifierCollection,
|
||||||
Opcode opcode, long timestamp, boolean encrypted)
|
Opcode opcode, long timestamp, boolean encrypted)
|
||||||
{
|
{
|
||||||
int lsn = channel.getValue();
|
DMRChannelGrantEvent event = mChannelGrantEventMap.get(channel);
|
||||||
|
|
||||||
DMRChannelGrantEvent event = mLSNGrantEventMap.get(lsn);
|
|
||||||
DecodeEventType decodeEventType = getEventType(opcode, identifierCollection, encrypted);
|
DecodeEventType decodeEventType = getEventType(opcode, identifierCollection, encrypted);
|
||||||
|
|
||||||
if(isStale(event, timestamp, identifierCollection)) //Create new event
|
if(isStale(event, timestamp, identifierCollection)) //Create new event
|
||||||
@@ -335,7 +333,7 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I
|
|||||||
.identifiers(identifierCollection)
|
.identifiers(identifierCollection)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
mLSNGrantEventMap.put(lsn, event);
|
mChannelGrantEventMap.put(channel, event);
|
||||||
|
|
||||||
}
|
}
|
||||||
else //Update current event
|
else //Update current event
|
||||||
@@ -355,7 +353,7 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I
|
|||||||
.identifiers(identifierCollection)
|
.identifiers(identifierCollection)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
mLSNGrantEventMap.put(lsn, event);
|
mChannelGrantEventMap.put(channel, event);
|
||||||
broadcast(event);
|
broadcast(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -643,37 +641,37 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I
|
|||||||
*/
|
*/
|
||||||
private void removeCallEvents(long frequency)
|
private void removeCallEvents(long frequency)
|
||||||
{
|
{
|
||||||
List<Integer> lsnsToRemove = new ArrayList<>();
|
List<DMRChannel> channelsToRemove = new ArrayList<>();
|
||||||
|
|
||||||
for(Map.Entry<Integer,DMRChannelGrantEvent> entry: mLSNGrantEventMap.entrySet())
|
for(Map.Entry<DMRChannel,DMRChannelGrantEvent> entry: mChannelGrantEventMap.entrySet())
|
||||||
{
|
{
|
||||||
if(entry.getValue().getChannelDescriptor().getDownlinkFrequency() == frequency)
|
if(entry.getKey().getDownlinkFrequency() == frequency)
|
||||||
{
|
{
|
||||||
lsnsToRemove.add(entry.getKey());
|
channelsToRemove.add(entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Integer lsn: lsnsToRemove)
|
for(DMRChannel channel: channelsToRemove)
|
||||||
{
|
{
|
||||||
mLSNGrantEventMap.remove(lsn);
|
mChannelGrantEventMap.remove(channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCallEventDetails(long frequency, String detailFragment)
|
private void updateCallEventDetails(long frequency, String detailFragment)
|
||||||
{
|
{
|
||||||
List<Integer> lsnsToUpdate = new ArrayList<>();
|
List<DMRChannel> channelsToUpdate = new ArrayList<>();
|
||||||
|
|
||||||
for(Map.Entry<Integer,DMRChannelGrantEvent> entry: mLSNGrantEventMap.entrySet())
|
for(Map.Entry<DMRChannel,DMRChannelGrantEvent> entry: mChannelGrantEventMap.entrySet())
|
||||||
{
|
{
|
||||||
if(entry.getValue().getChannelDescriptor().getDownlinkFrequency() == frequency)
|
if(entry.getValue().getChannelDescriptor().getDownlinkFrequency() == frequency)
|
||||||
{
|
{
|
||||||
lsnsToUpdate.add(entry.getKey());
|
channelsToUpdate.add(entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Integer lsn: lsnsToUpdate)
|
for(DMRChannel channel: channelsToUpdate)
|
||||||
{
|
{
|
||||||
DMRChannelGrantEvent event = mLSNGrantEventMap.get(lsn);
|
DMRChannelGrantEvent event = mChannelGrantEventMap.get(channel);
|
||||||
|
|
||||||
if(event != null)
|
if(event != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import io.github.dsheirer.identifier.Role;
|
|||||||
import io.github.dsheirer.identifier.integer.IntegerIdentifier;
|
import io.github.dsheirer.identifier.integer.IntegerIdentifier;
|
||||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBand;
|
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBand;
|
||||||
import io.github.dsheirer.protocol.Protocol;
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,8 +35,9 @@ import org.apache.commons.lang3.Validate;
|
|||||||
*
|
*
|
||||||
* Note: timeslots are tracked as 1 and 2
|
* Note: timeslots are tracked as 1 and 2
|
||||||
*/
|
*/
|
||||||
public abstract class DMRChannel extends IntegerIdentifier implements IChannelDescriptor
|
public abstract class DMRChannel extends IntegerIdentifier implements IChannelDescriptor, ITimeslotFrequencyReceiver
|
||||||
{
|
{
|
||||||
|
private TimeslotFrequency mTimeslotFrequency;
|
||||||
private int mTimeslot;
|
private int mTimeslot;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,13 +59,23 @@ public abstract class DMRChannel extends IntegerIdentifier implements IChannelDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repeater number or channel number for the channel.
|
* Repeater number aka Logical Channel Number (LCN) for the channel.
|
||||||
*/
|
*/
|
||||||
public int getChannel()
|
public int getChannelNumber()
|
||||||
{
|
{
|
||||||
return getValue();
|
return getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method to format the single channel number as an array for TimeslotFrequency matching.
|
||||||
|
* @return channel number as an integer array.
|
||||||
|
*/
|
||||||
|
public int[] getLogicalChannelNumbers()
|
||||||
|
{
|
||||||
|
return new int[]{getChannelNumber()};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timeslot for the channel.
|
* Timeslot for the channel.
|
||||||
* @return timeslot as zero-based index with values in range: 0 or 1.
|
* @return timeslot as zero-based index with values in range: 0 or 1.
|
||||||
@@ -95,7 +108,7 @@ public abstract class DMRChannel extends IntegerIdentifier implements IChannelDe
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "CHAN:" + getChannel() + ":" + getTimeslot();
|
return "CHAN:" + getChannelNumber() + ":" + getTimeslot();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,4 +128,72 @@ public abstract class DMRChannel extends IntegerIdentifier implements IChannelDe
|
|||||||
{
|
{
|
||||||
throw new IllegalArgumentException("This method is not supported");
|
throw new IllegalArgumentException("This method is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDownlinkFrequency()
|
||||||
|
{
|
||||||
|
if(mTimeslotFrequency != null)
|
||||||
|
{
|
||||||
|
return mTimeslotFrequency.getDownlinkFrequency();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getUplinkFrequency()
|
||||||
|
{
|
||||||
|
if(mTimeslotFrequency != null)
|
||||||
|
{
|
||||||
|
return mTimeslotFrequency.getUplinkFrequency();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the lsn to frequency mapper value.
|
||||||
|
* @param timeslotFrequency to set
|
||||||
|
*/
|
||||||
|
public void setTimeslotFrequency(TimeslotFrequency timeslotFrequency)
|
||||||
|
{
|
||||||
|
mTimeslotFrequency = timeslotFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
|
{
|
||||||
|
for(TimeslotFrequency timeslotFrequency: timeslotFrequencies)
|
||||||
|
{
|
||||||
|
if(timeslotFrequency.getChannelNumber() == getChannelNumber())
|
||||||
|
{
|
||||||
|
setTimeslotFrequency(timeslotFrequency);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o)
|
||||||
|
{
|
||||||
|
if(this == o)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(!(o instanceof DMRChannel that))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!super.equals(o))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return getTimeslot() == that.getTimeslot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
return Objects.hash(super.hashCode(), getTimeslot());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
package io.github.dsheirer.module.decode.dmr.channel;
|
package io.github.dsheirer.module.decode.dmr.channel;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DMR Logical Slot Number (LSN) channel.
|
* DMR Logical Slot Number (LSN) channel.
|
||||||
*
|
*
|
||||||
@@ -44,10 +42,8 @@ import java.util.List;
|
|||||||
* 15: 8/1
|
* 15: 8/1
|
||||||
* 16: 8/2
|
* 16: 8/2
|
||||||
*/
|
*/
|
||||||
public class DMRLsn extends DMRChannel implements ITimeslotFrequencyReceiver
|
public class DMRLsn extends DMRChannel
|
||||||
{
|
{
|
||||||
private TimeslotFrequency mTimeslotFrequency;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
*
|
*
|
||||||
@@ -61,7 +57,7 @@ public class DMRLsn extends DMRChannel implements ITimeslotFrequencyReceiver
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "LSN:" + getLsn();
|
return "LSN:" + getLsn() + " LCN:" + getChannelNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,65 +66,7 @@ public class DMRLsn extends DMRChannel implements ITimeslotFrequencyReceiver
|
|||||||
*/
|
*/
|
||||||
public int getLsn()
|
public int getLsn()
|
||||||
{
|
{
|
||||||
return ((getChannel() - 1) * 2) + getTimeslot();
|
return ((getChannelNumber() - 1) * 2) + getTimeslot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDownlinkFrequency()
|
|
||||||
{
|
|
||||||
if(mTimeslotFrequency != null)
|
|
||||||
{
|
|
||||||
return mTimeslotFrequency.getDownlinkFrequency();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getUplinkFrequency()
|
|
||||||
{
|
|
||||||
if(mTimeslotFrequency != null)
|
|
||||||
{
|
|
||||||
return mTimeslotFrequency.getUplinkFrequency();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getLogicalSlotNumbers()
|
|
||||||
{
|
|
||||||
return new int[]{getLsn()};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the lsn to frequency mapper value.
|
|
||||||
* @param timeslotFrequency to set
|
|
||||||
*/
|
|
||||||
public void setTimeslotFrequency(TimeslotFrequency timeslotFrequency)
|
|
||||||
{
|
|
||||||
mTimeslotFrequency = timeslotFrequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
|
||||||
{
|
|
||||||
for(TimeslotFrequency timeslotFrequency: timeslotFrequencies)
|
|
||||||
{
|
|
||||||
if(timeslotFrequency.getNumber() == getLsn())
|
|
||||||
{
|
|
||||||
setTimeslotFrequency(timeslotFrequency);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
for(int x = 1; x <= 16; x++)
|
|
||||||
{
|
|
||||||
DMRLsn lsn = new DmrRestLsn(x);
|
|
||||||
System.out.println(lsn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,14 +24,12 @@ package io.github.dsheirer.module.decode.dmr.channel;
|
|||||||
*/
|
*/
|
||||||
public class DMRTier3Channel extends DMRChannel
|
public class DMRTier3Channel extends DMRChannel
|
||||||
{
|
{
|
||||||
private TimeslotFrequency mTimeslotFrequency;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance. Note: radio reference uses a one based index, so we add a value of one to the
|
* Constructs an instance. Note: radio reference uses a one based index, so we add a value of one to the
|
||||||
* calculated logical slot value for visual compatibility for users.
|
* calculated logical slot value for visual compatibility for users.
|
||||||
*
|
*
|
||||||
* @param channel number or repeater number
|
* @param channel number or repeater number
|
||||||
* @param logicalSlotNumber - zero based index.
|
* @param timeslot either 1 or 2.
|
||||||
*/
|
*/
|
||||||
public DMRTier3Channel(int channel, int timeslot)
|
public DMRTier3Channel(int channel, int timeslot)
|
||||||
{
|
{
|
||||||
@@ -39,42 +37,12 @@ public class DMRTier3Channel extends DMRChannel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downlink frequency
|
* Tier III Channel ID
|
||||||
* @return value in Hertz, or 0 if this channel doesn't have a timeslot frequency mapping
|
* @return channel ID
|
||||||
*/
|
*/
|
||||||
@Override
|
public int getChannelId()
|
||||||
public long getDownlinkFrequency()
|
|
||||||
{
|
{
|
||||||
if(mTimeslotFrequency != null)
|
return getChannelNumber() * 2 + getTimeslot();
|
||||||
{
|
|
||||||
return mTimeslotFrequency.getDownlinkFrequency();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uplink frequency
|
|
||||||
* @return value in Hertz, or 0 if this channel doesn't have a timeslot frequency mapping
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public long getUplinkFrequency()
|
|
||||||
{
|
|
||||||
if(mTimeslotFrequency != null)
|
|
||||||
{
|
|
||||||
return mTimeslotFrequency.getUplinkFrequency();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the timeslot frequency mapping
|
|
||||||
* @param timeslotFrequency
|
|
||||||
*/
|
|
||||||
public void setTimeslotFrequency(TimeslotFrequency timeslotFrequency)
|
|
||||||
{
|
|
||||||
mTimeslotFrequency = timeslotFrequency;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,7 +51,8 @@ public class DMRTier3Channel extends DMRChannel
|
|||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(" LCN:").append(getValue());
|
sb.append(" LCN:").append(getChannelNumber());
|
||||||
|
sb.append(" CHANID:").append(getChannelId());
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ import java.util.List;
|
|||||||
public interface ITimeslotFrequencyReceiver
|
public interface ITimeslotFrequencyReceiver
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Provides the logical slot number(s) that require a matching timeslot frequency mapping
|
* Provides the logical channel number(s) that require a matching timeslot frequency mapping
|
||||||
*/
|
*/
|
||||||
public int[] getLogicalSlotNumbers();
|
public int[] getLogicalChannelNumbers();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the list of timeslot frequency mappings to the implementer
|
* Applies the list of timeslot frequency mappings to the implementer
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import javafx.beans.property.SimpleLongProperty;
|
|||||||
import javafx.util.Callback;
|
import javafx.util.Callback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a logical slot number (LSN) to a pair of channel frequency values
|
* Maps a logical channel number (LCN) to a pair of channel frequency values
|
||||||
*/
|
*/
|
||||||
public class TimeslotFrequency
|
public class TimeslotFrequency
|
||||||
{
|
{
|
||||||
@@ -100,7 +100,10 @@ public class TimeslotFrequency
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logical slot number (LSN) as a 1-index based counter
|
* Logical channel number (LCN) as a 1-index based counter
|
||||||
|
*
|
||||||
|
* Note: lsn (logical slot number) is a legacy name for this field. The field currently holds the LCN or logical
|
||||||
|
* channel number. To avoid breaking serialization, we leave this field labeled as lsn.
|
||||||
*/
|
*/
|
||||||
@JacksonXmlProperty(isAttribute = true, localName = "lsn")
|
@JacksonXmlProperty(isAttribute = true, localName = "lsn")
|
||||||
public int getNumber()
|
public int getNumber()
|
||||||
@@ -109,12 +112,52 @@ public class TimeslotFrequency
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the logical slot number (LSN) as a 1-index start
|
* Logical channel number which is the same value as getNumber.
|
||||||
* @param lsn where LSN 1 is the first slot, 2 the second, etc
|
* @return
|
||||||
*/
|
*/
|
||||||
public void setNumber(int lsn)
|
@JsonIgnore
|
||||||
|
public int getChannelNumber()
|
||||||
{
|
{
|
||||||
mNumberProperty.set(lsn);
|
return getNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public String getLogicalSlotNumbers()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
int channel = getChannelNumber();
|
||||||
|
|
||||||
|
if(channel > 0)
|
||||||
|
{
|
||||||
|
if(channel < 32) //Connect Plus uses 5-bits for LSN for a maximum value of 31
|
||||||
|
{
|
||||||
|
//Cap+ & Con+ Logical Slot Numbers
|
||||||
|
int lsn1 = (channel - 1) * 2 + 1;
|
||||||
|
int lsn2 = (channel - 1) * 2 + 2;
|
||||||
|
sb.append("LSN:").append(lsn1).append("/").append(lsn2).append(" or ");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Tier III channel IDs
|
||||||
|
int chanId1 = channel * 2 + 1;
|
||||||
|
int chanId2 = channel * 2 + 2;
|
||||||
|
sb.append("Tier3 Chan:").append(chanId1).append("/").append(chanId2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append("(empty)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the logical channel number (LCN) as a 1-index start
|
||||||
|
* @param lcn where LCN 1 is logical slot numbers (LSN) 1 and 2, LCN2=LSN3/4, etc.
|
||||||
|
*/
|
||||||
|
public void setNumber(int lcn)
|
||||||
|
{
|
||||||
|
mNumberProperty.set(lcn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,7 +203,7 @@ public class TimeslotFrequency
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "TIMESLOT LSN:" + getNumber() + " DOWNLINK:" + getDownlinkFrequency();
|
return "LCN:" + getNumber() + " DOWNLINK:" + getDownlinkFrequency();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -299,9 +299,9 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getLogicalSlotNumbers()
|
public int[] getLogicalChannelNumbers()
|
||||||
{
|
{
|
||||||
return getRestChannel().getLogicalSlotNumbers();
|
return getRestChannel().getLogicalChannelNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -312,13 +312,7 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ
|
|||||||
@Override
|
@Override
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
{
|
{
|
||||||
for(TimeslotFrequency timeslotFrequency : timeslotFrequencies)
|
getRestChannel().apply(timeslotFrequencies);
|
||||||
{
|
|
||||||
if(timeslotFrequency.getNumber() == getRestChannel().getValue())
|
|
||||||
{
|
|
||||||
getRestChannel().setTimeslotFrequency(timeslotFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -299,9 +299,9 @@ public class CapacityPlusSiteStatus extends CSBKMessage implements ITimeslotFreq
|
|||||||
* Logical slot numbers that require slot to frequency mappings.
|
* Logical slot numbers that require slot to frequency mappings.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int[] getLogicalSlotNumbers()
|
public int[] getLogicalChannelNumbers()
|
||||||
{
|
{
|
||||||
return getRestChannel().getLogicalSlotNumbers();
|
return getRestChannel().getLogicalChannelNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -312,13 +312,7 @@ public class CapacityPlusSiteStatus extends CSBKMessage implements ITimeslotFreq
|
|||||||
@Override
|
@Override
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
{
|
{
|
||||||
for(TimeslotFrequency timeslotFrequency : timeslotFrequencies)
|
getRestChannel().apply(timeslotFrequencies);
|
||||||
{
|
|
||||||
if(getRestChannel().getValue() == timeslotFrequency.getNumber())
|
|
||||||
{
|
|
||||||
getRestChannel().setTimeslotFrequency(timeslotFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class ConnectPlusDataChannelGrant extends CSBKMessage implements ITimeslo
|
|||||||
{
|
{
|
||||||
private static final int[] TARGET_ADDRESS = new int[]{16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
private static final int[] TARGET_ADDRESS = new int[]{16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||||
32, 33, 34, 35, 36, 37, 38, 39};
|
32, 33, 34, 35, 36, 37, 38, 39};
|
||||||
private static final int[] REPEATER = new int[]{40, 41, 42, 43, 44};
|
private static final int[] LOGICAL_SLOT_NUMBER = new int[]{40, 41, 42, 43, 44};
|
||||||
|
|
||||||
//Analysis: this field correlates to UNKNOWN_FIELD_1(bits: 40-48) in ConnectPlusTerminateChannelGrant.
|
//Analysis: this field correlates to UNKNOWN_FIELD_1(bits: 40-48) in ConnectPlusTerminateChannelGrant.
|
||||||
private static final int[] UNKNOWN_FIELD = new int[]{48, 49, 50, 51, 52, 53, 54, 55};
|
private static final int[] UNKNOWN_FIELD = new int[]{48, 49, 50, 51, 52, 53, 54, 55};
|
||||||
@@ -109,11 +109,11 @@ public class ConnectPlusDataChannelGrant extends CSBKMessage implements ITimeslo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Channel grant repeater number
|
* Channel grant logical slot number
|
||||||
*/
|
*/
|
||||||
public int getRepeater()
|
public int getLsn()
|
||||||
{
|
{
|
||||||
return getMessage().getInt(REPEATER);
|
return getMessage().getInt(LOGICAL_SLOT_NUMBER) - 1; //Don't change this ... always subtract 1 to get the repeater LSN
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,16 +123,16 @@ public class ConnectPlusDataChannelGrant extends CSBKMessage implements ITimeslo
|
|||||||
{
|
{
|
||||||
if(mDmrLsn == null)
|
if(mDmrLsn == null)
|
||||||
{
|
{
|
||||||
mDmrLsn = new DMRLsn(getRepeater());
|
mDmrLsn = new DMRLsn(getLsn());
|
||||||
}
|
}
|
||||||
|
|
||||||
return mDmrLsn;
|
return mDmrLsn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getLogicalSlotNumbers()
|
public int[] getLogicalChannelNumbers()
|
||||||
{
|
{
|
||||||
return getChannel().getLogicalSlotNumbers();
|
return getChannel().getLogicalChannelNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,13 +142,7 @@ public class ConnectPlusDataChannelGrant extends CSBKMessage implements ITimeslo
|
|||||||
@Override
|
@Override
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
{
|
{
|
||||||
for(TimeslotFrequency timeslotFrequency: timeslotFrequencies)
|
getChannel().apply(timeslotFrequencies);
|
||||||
{
|
|
||||||
if(timeslotFrequency.getNumber() == getChannel().getValue())
|
|
||||||
{
|
|
||||||
getChannel().setTimeslotFrequency(timeslotFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class ConnectPlusOTAAnnouncement extends CSBKMessage implements ITimeslot
|
|||||||
private static final int[] VERSION = new int[]{24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
private static final int[] VERSION = new int[]{24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||||
private static final int[] UNKNOWN = new int[]{40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
private static final int[] UNKNOWN = new int[]{40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
||||||
57, 58, 59, 60, 61, 62};
|
57, 58, 59, 60, 61, 62};
|
||||||
private static final int[] DATA_REPEATER = new int[]{63, 64, 65, 66, 67};
|
private static final int[] LOGICAL_SLOT_NUMBER = new int[]{63, 64, 65, 66, 67};
|
||||||
|
|
||||||
private DMRLsn mDataChannel;
|
private DMRLsn mDataChannel;
|
||||||
private List<Identifier> mIdentifiers;
|
private List<Identifier> mIdentifiers;
|
||||||
@@ -99,11 +99,11 @@ public class ConnectPlusOTAAnnouncement extends CSBKMessage implements ITimeslot
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data repeater number
|
* Data logical slot numberrepeater number
|
||||||
*/
|
*/
|
||||||
public int getDataRepeater()
|
public int getDataLsn()
|
||||||
{
|
{
|
||||||
return getMessage().getInt(DATA_REPEATER);
|
return getMessage().getInt(LOGICAL_SLOT_NUMBER) - 1; //Leave this as minus 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,16 +113,16 @@ public class ConnectPlusOTAAnnouncement extends CSBKMessage implements ITimeslot
|
|||||||
{
|
{
|
||||||
if(mDataChannel == null)
|
if(mDataChannel == null)
|
||||||
{
|
{
|
||||||
mDataChannel = new DMRLsn(getDataRepeater());
|
mDataChannel = new DMRLsn(getDataLsn());
|
||||||
}
|
}
|
||||||
|
|
||||||
return mDataChannel;
|
return mDataChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getLogicalSlotNumbers()
|
public int[] getLogicalChannelNumbers()
|
||||||
{
|
{
|
||||||
return getDataChannel().getLogicalSlotNumbers();
|
return getDataChannel().getLogicalChannelNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,13 +133,7 @@ public class ConnectPlusOTAAnnouncement extends CSBKMessage implements ITimeslot
|
|||||||
@Override
|
@Override
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
{
|
{
|
||||||
for(TimeslotFrequency timeslotFrequency : timeslotFrequencies)
|
getDataChannel().apply(timeslotFrequencies);
|
||||||
{
|
|
||||||
if(timeslotFrequency.getNumber() == getDataChannel().getValue())
|
|
||||||
{
|
|
||||||
getDataChannel().setTimeslotFrequency(timeslotFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class ConnectPlusVoiceChannelUser extends CSBKMessage implements ITimeslo
|
|||||||
32, 33, 34, 35, 36, 37, 38, 39};
|
32, 33, 34, 35, 36, 37, 38, 39};
|
||||||
private static final int[] GROUP_ADDRESS = new int[]{40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
|
private static final int[] GROUP_ADDRESS = new int[]{40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
|
||||||
56, 57, 58, 59, 60, 61, 62, 63};
|
56, 57, 58, 59, 60, 61, 62, 63};
|
||||||
private static final int[] TRAFFIC_CHANNEL_REPEATER = new int[]{64, 65, 66, 67, 68};
|
private static final int[] LOGICAL_SLOT_NUMBER = new int[]{64, 65, 66, 67, 68};
|
||||||
private static final int[] UNKNOWN_FIELD = new int[]{72, 73, 74, 75, 76, 77, 78, 79};
|
private static final int[] UNKNOWN_FIELD = new int[]{72, 73, 74, 75, 76, 77, 78, 79};
|
||||||
|
|
||||||
private RadioIdentifier mRadio;
|
private RadioIdentifier mRadio;
|
||||||
@@ -126,9 +126,9 @@ public class ConnectPlusVoiceChannelUser extends CSBKMessage implements ITimeslo
|
|||||||
/**
|
/**
|
||||||
* Traffic channel repeater
|
* Traffic channel repeater
|
||||||
*/
|
*/
|
||||||
public int getTrafficChannelRepeater()
|
public int getTrafficLsn()
|
||||||
{
|
{
|
||||||
return getMessage().getInt(TRAFFIC_CHANNEL_REPEATER);
|
return getMessage().getInt(LOGICAL_SLOT_NUMBER) - 1; //Always leave as minus 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -138,16 +138,16 @@ public class ConnectPlusVoiceChannelUser extends CSBKMessage implements ITimeslo
|
|||||||
{
|
{
|
||||||
if(mDmrLsn == null)
|
if(mDmrLsn == null)
|
||||||
{
|
{
|
||||||
mDmrLsn = new DMRLsn(getTrafficChannelRepeater());
|
mDmrLsn = new DMRLsn(getTrafficLsn());
|
||||||
}
|
}
|
||||||
|
|
||||||
return mDmrLsn;
|
return mDmrLsn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getLogicalSlotNumbers()
|
public int[] getLogicalChannelNumbers()
|
||||||
{
|
{
|
||||||
return getChannel().getLogicalSlotNumbers();
|
return getChannel().getLogicalChannelNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,13 +157,7 @@ public class ConnectPlusVoiceChannelUser extends CSBKMessage implements ITimeslo
|
|||||||
@Override
|
@Override
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
{
|
{
|
||||||
for(TimeslotFrequency timeslotFrequency: timeslotFrequencies)
|
getChannel().apply(timeslotFrequencies);
|
||||||
{
|
|
||||||
if(timeslotFrequency.getNumber() == getChannel().getValue())
|
|
||||||
{
|
|
||||||
getChannel().setTimeslotFrequency(timeslotFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import io.github.dsheirer.identifier.integer.IntegerIdentifier;
|
|||||||
import io.github.dsheirer.identifier.radio.RadioIdentifier;
|
import io.github.dsheirer.identifier.radio.RadioIdentifier;
|
||||||
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.DMRChannel;
|
import io.github.dsheirer.module.decode.dmr.channel.DMRChannel;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.DMRLsn;
|
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.DMRTier3Channel;
|
import io.github.dsheirer.module.decode.dmr.channel.DMRTier3Channel;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
|
import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
||||||
@@ -224,11 +223,11 @@ public class Clear extends CSBKMessage implements ITimeslotFrequencyReceiver
|
|||||||
* Logical Slot Number(s) for channels contained in this message
|
* Logical Slot Number(s) for channels contained in this message
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int[] getLogicalSlotNumbers()
|
public int[] getLogicalChannelNumbers()
|
||||||
{
|
{
|
||||||
if(getMoveToChannel() instanceof DMRLsn dmrLsn)
|
if(getMoveToChannel() != null)
|
||||||
{
|
{
|
||||||
return dmrLsn.getLogicalSlotNumbers();
|
return getMoveToChannel().getLogicalChannelNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new int[0];
|
return new int[0];
|
||||||
@@ -241,17 +240,9 @@ public class Clear extends CSBKMessage implements ITimeslotFrequencyReceiver
|
|||||||
@Override
|
@Override
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
{
|
{
|
||||||
if(getMoveToChannel() instanceof DMRTier3Channel)
|
if(getMoveToChannel() != null)
|
||||||
{
|
{
|
||||||
DMRTier3Channel channel = (DMRTier3Channel)getMoveToChannel();
|
getMoveToChannel().apply(timeslotFrequencies);
|
||||||
|
|
||||||
for(TimeslotFrequency timeslotFrequency: timeslotFrequencies)
|
|
||||||
{
|
|
||||||
if(channel.getValue() == timeslotFrequency.getNumber())
|
|
||||||
{
|
|
||||||
channel.setTimeslotFrequency(timeslotFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,8 @@ public class MoveTSCC extends CSBKMessage
|
|||||||
|
|
||||||
if(multiBlock != null)
|
if(multiBlock != null)
|
||||||
{
|
{
|
||||||
mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 0);
|
//Timeslot hard-coded to 1 since this is a control channel.
|
||||||
|
mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ public class AdjacentSiteInformation extends Announcement
|
|||||||
|
|
||||||
if(multiBlock != null)
|
if(multiBlock != null)
|
||||||
{
|
{
|
||||||
//Timeslot hard-coded to zero for control channel
|
//Timeslot hard-coded to one for control channel
|
||||||
mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 0);
|
mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -27,7 +27,6 @@ import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
|||||||
import io.github.dsheirer.module.decode.dmr.message.data.mbc.MBCContinuationBlock;
|
import io.github.dsheirer.module.decode.dmr.message.data.mbc.MBCContinuationBlock;
|
||||||
import io.github.dsheirer.module.decode.dmr.message.type.AbsoluteChannelParameters;
|
import io.github.dsheirer.module.decode.dmr.message.type.AbsoluteChannelParameters;
|
||||||
import io.github.dsheirer.module.decode.dmr.message.type.DataType;
|
import io.github.dsheirer.module.decode.dmr.message.type.DataType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -56,7 +55,8 @@ public class AnnounceChannelFrequency extends Announcement
|
|||||||
|
|
||||||
if(multiBlock != null)
|
if(multiBlock != null)
|
||||||
{
|
{
|
||||||
mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 0);
|
//Timeslot hard-coded to one
|
||||||
|
mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ public class AnnounceWithdrawTSCC extends Announcement
|
|||||||
|
|
||||||
if(multiBlock != null)
|
if(multiBlock != null)
|
||||||
{
|
{
|
||||||
//Control channel timeslot hard-coded to 0
|
//Control channel timeslot hard-coded to 1
|
||||||
mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 0);
|
mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
|||||||
import io.github.dsheirer.identifier.Identifier;
|
import io.github.dsheirer.identifier.Identifier;
|
||||||
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.DMRChannel;
|
import io.github.dsheirer.module.decode.dmr.channel.DMRChannel;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.DMRLsn;
|
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.DMRTier3Channel;
|
import io.github.dsheirer.module.decode.dmr.channel.DMRTier3Channel;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
|
import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
||||||
@@ -90,7 +89,8 @@ public class VoteNowAdvice extends Announcement implements ITimeslotFrequencyRec
|
|||||||
|
|
||||||
if(multiBlock != null)
|
if(multiBlock != null)
|
||||||
{
|
{
|
||||||
mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 0);
|
//Timeslot hard-coded to one for control channel
|
||||||
|
mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,11 +239,11 @@ public class VoteNowAdvice extends Announcement implements ITimeslotFrequencyRec
|
|||||||
* Logical Slot Number(s) for channels contained in this message
|
* Logical Slot Number(s) for channels contained in this message
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int[] getLogicalSlotNumbers()
|
public int[] getLogicalChannelNumbers()
|
||||||
{
|
{
|
||||||
if(getChannel() instanceof DMRLsn dmrLsn)
|
if(getChannel() != null)
|
||||||
{
|
{
|
||||||
return dmrLsn.getLogicalSlotNumbers();
|
return getChannel().getLogicalChannelNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new int[0];
|
return new int[0];
|
||||||
@@ -256,17 +256,9 @@ public class VoteNowAdvice extends Announcement implements ITimeslotFrequencyRec
|
|||||||
@Override
|
@Override
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
{
|
{
|
||||||
if(getChannel() instanceof DMRTier3Channel)
|
if(getChannel() != null)
|
||||||
{
|
{
|
||||||
DMRTier3Channel channel = (DMRTier3Channel)getChannel();
|
getChannel().apply(timeslotFrequencies);
|
||||||
|
|
||||||
for(TimeslotFrequency timeslotFrequency: timeslotFrequencies)
|
|
||||||
{
|
|
||||||
if(channel.getValue() == timeslotFrequency.getNumber())
|
|
||||||
{
|
|
||||||
channel.setTimeslotFrequency(timeslotFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class BroadcastTalkgroupVoiceChannelGrant extends ChannelGrant
|
|||||||
|
|
||||||
sb.append(" BROADCAST TALKGROUP VOICE CHANNEL GRANT FM:").append(getSourceRadio());
|
sb.append(" BROADCAST TALKGROUP VOICE CHANNEL GRANT FM:").append(getSourceRadio());
|
||||||
sb.append(" TO:").append(getDestinationTalkgroup());
|
sb.append(" TO:").append(getDestinationTalkgroup());
|
||||||
sb.append(" CHAN:").append(getChannel());
|
sb.append(" ").append(getChannel());
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ package io.github.dsheirer.module.decode.dmr.message.data.csbk.standard.grant;
|
|||||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||||
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.DMRChannel;
|
import io.github.dsheirer.module.decode.dmr.channel.DMRChannel;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.DMRLsn;
|
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.DMRTier3Channel;
|
import io.github.dsheirer.module.decode.dmr.channel.DMRTier3Channel;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
|
import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
||||||
@@ -158,11 +157,11 @@ public abstract class ChannelGrant extends CSBKMessage implements ITimeslotFrequ
|
|||||||
* Logical Slot Number(s) for channels contained in this message
|
* Logical Slot Number(s) for channels contained in this message
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int[] getLogicalSlotNumbers()
|
public int[] getLogicalChannelNumbers()
|
||||||
{
|
{
|
||||||
if(getChannel() instanceof DMRLsn dmrLsn)
|
if(getChannel() != null)
|
||||||
{
|
{
|
||||||
return dmrLsn.getLogicalSlotNumbers();
|
return getChannel().getLogicalChannelNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new int[0];
|
return new int[0];
|
||||||
@@ -175,17 +174,9 @@ public abstract class ChannelGrant extends CSBKMessage implements ITimeslotFrequ
|
|||||||
@Override
|
@Override
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
{
|
{
|
||||||
if(getChannel() instanceof DMRTier3Channel)
|
if(getChannel() != null)
|
||||||
{
|
{
|
||||||
DMRTier3Channel channel = (DMRTier3Channel)getChannel();
|
getChannel().apply(timeslotFrequencies);
|
||||||
|
|
||||||
for(TimeslotFrequency timeslotFrequency: timeslotFrequencies)
|
|
||||||
{
|
|
||||||
if(channel.getValue() == timeslotFrequency.getNumber())
|
|
||||||
{
|
|
||||||
channel.setTimeslotFrequency(timeslotFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public class DuplexPrivateDataChannelGrant extends ChannelGrant
|
|||||||
|
|
||||||
sb.append(" DUPLEX PRIVATE DATA CHANNEL GRANT FM:").append(getSourceRadio());
|
sb.append(" DUPLEX PRIVATE DATA CHANNEL GRANT FM:").append(getSourceRadio());
|
||||||
sb.append(" TO:").append(getDestinationRadio());
|
sb.append(" TO:").append(getDestinationRadio());
|
||||||
sb.append(" CHAN:").append(getChannel());
|
sb.append(" ").append(getChannel());
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public class DuplexPrivateVoiceChannelGrant extends ChannelGrant
|
|||||||
|
|
||||||
sb.append(" DUPLEX PRIVATE VOICE CHANNEL GRANT FM:").append(getSourceRadio());
|
sb.append(" DUPLEX PRIVATE VOICE CHANNEL GRANT FM:").append(getSourceRadio());
|
||||||
sb.append(" TO:").append(getDestinationRadio());
|
sb.append(" TO:").append(getDestinationRadio());
|
||||||
sb.append(" CHAN:").append(getChannel());
|
sb.append(" ").append(getChannel());
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ public class PrivateDataChannelGrant extends ChannelGrant
|
|||||||
|
|
||||||
sb.append(" PRIVATE DATA CHANNEL GRANT FM:").append(getSourceRadio());
|
sb.append(" PRIVATE DATA CHANNEL GRANT FM:").append(getSourceRadio());
|
||||||
sb.append(" TO:").append(getDestinationRadio());
|
sb.append(" TO:").append(getDestinationRadio());
|
||||||
sb.append(" CHAN:").append(getChannel());
|
sb.append(" ").append(getChannel());
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ public class PrivateVoiceChannelGrant extends ChannelGrant
|
|||||||
|
|
||||||
sb.append(" PRIVATE VOICE CHANNEL GRANT FM:").append(getSourceRadio());
|
sb.append(" PRIVATE VOICE CHANNEL GRANT FM:").append(getSourceRadio());
|
||||||
sb.append(" TO:").append(getDestinationRadio());
|
sb.append(" TO:").append(getDestinationRadio());
|
||||||
sb.append(" CHAN:").append(getChannel());
|
sb.append(" ").append(getChannel());
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class TalkgroupDataChannelGrant extends ChannelGrant
|
|||||||
|
|
||||||
sb.append(" TALKGROUP DATA CHANNEL GRANT FM:").append(getSourceRadio());
|
sb.append(" TALKGROUP DATA CHANNEL GRANT FM:").append(getSourceRadio());
|
||||||
sb.append(" TO:").append(getDestinationTalkgroup());
|
sb.append(" TO:").append(getDestinationTalkgroup());
|
||||||
sb.append(" CHAN:").append(getChannel());
|
sb.append(" ").append(getChannel());
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class TalkgroupVoiceChannelGrant extends ChannelGrant
|
|||||||
|
|
||||||
sb.append(" TALKGROUP VOICE CHANNEL GRANT FM:").append(getSourceRadio());
|
sb.append(" TALKGROUP VOICE CHANNEL GRANT FM:").append(getSourceRadio());
|
||||||
sb.append(" TO:").append(getDestinationTalkgroup());
|
sb.append(" TO:").append(getDestinationTalkgroup());
|
||||||
sb.append(" CHAN:").append(getChannel());
|
sb.append(" ").append(getChannel());
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -176,9 +176,9 @@ public class CapacityPlusWideAreaVoiceChannelUser extends CapacityPlusVoiceChann
|
|||||||
* Exposes the rest channel logical slot number so that a LSN to frequency map can be applied to this message.
|
* Exposes the rest channel logical slot number so that a LSN to frequency map can be applied to this message.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int[] getLogicalSlotNumbers()
|
public int[] getLogicalChannelNumbers()
|
||||||
{
|
{
|
||||||
return getRestChannel().getLogicalSlotNumbers();
|
return getRestChannel().getLogicalChannelNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -189,12 +189,6 @@ public class CapacityPlusWideAreaVoiceChannelUser extends CapacityPlusVoiceChann
|
|||||||
@Override
|
@Override
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
{
|
{
|
||||||
for(TimeslotFrequency timeslotFrequency : timeslotFrequencies)
|
getRestChannel().apply(timeslotFrequencies);
|
||||||
{
|
|
||||||
if(getRestChannel().getValue() == timeslotFrequency.getNumber())
|
|
||||||
{
|
|
||||||
getRestChannel().setTimeslotFrequency(timeslotFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,9 +105,9 @@ public class CapacityPlusRestChannel extends ShortLCMessage implements ITimeslot
|
|||||||
* Exposes the rest channel logical slot number so that a LSN to frequency map can be applied to this message.
|
* Exposes the rest channel logical slot number so that a LSN to frequency map can be applied to this message.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int[] getLogicalSlotNumbers()
|
public int[] getLogicalChannelNumbers()
|
||||||
{
|
{
|
||||||
return getRestChannel().getLogicalSlotNumbers();
|
return getRestChannel().getLogicalChannelNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,13 +117,7 @@ public class CapacityPlusRestChannel extends ShortLCMessage implements ITimeslot
|
|||||||
@Override
|
@Override
|
||||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||||
{
|
{
|
||||||
for(TimeslotFrequency timeslotFrequency: timeslotFrequencies)
|
getRestChannel().apply(timeslotFrequencies);
|
||||||
{
|
|
||||||
if(getRestChannel().getValue() == timeslotFrequency.getNumber())
|
|
||||||
{
|
|
||||||
getRestChannel().setTimeslotFrequency(timeslotFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ public class DecodeEventPanel extends JPanel implements Listener<ProcessingChain
|
|||||||
sb.append(",");
|
sb.append(",");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(identifier.getForm() == Form.TALKGROUP)
|
if(identifier.getForm() == Form.TALKGROUP || identifier.getForm() == Form.RADIO || identifier.getForm() == Form.PATCH_GROUP)
|
||||||
{
|
{
|
||||||
sb.append(mUserPreferences.getTalkgroupFormatPreference().format(identifier));
|
sb.append(mUserPreferences.getTalkgroupFormatPreference().format(identifier));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user