From 77d725a488c1d6ebb34b4c6ac60b92557ec1da0f Mon Sep 17 00:00:00 2001 From: Dennis Sheirer Date: Thu, 31 Aug 2023 07:06:50 -0400 Subject: [PATCH] #1637 Resolves issue with DMR Cap+/CapMax trunking channel to frequency map. Updates the DMR channel map to use LCN instead of LSN and aligns standard DMR with Tier-III DMR for channel identification. Warning: breaking change. Users will need to either recreate their DMR channel to frequency maps or simply delete and reload the channel from Radio Reference to correct the channel to frequency map. Updates the DMR Decoder State to better track and update DMR events versus creating a new event and causing lots of scrolling in the event window of the Now Playing tab. --- .../channelizer/PolyphaseChannelManager.java | 5 +- .../channel/DMRConfigurationEditor.java | 52 ++++++----- .../radioreference/RadioReferenceDecoder.java | 21 ++--- .../module/decode/dmr/DMRDecoderState.java | 72 ++++++++------- .../decode/dmr/DMRMessageProcessor.java | 10 +-- .../dmr/DMRNetworkConfigurationMonitor.java | 36 ++++---- .../decode/dmr/DMRTrafficChannelManager.java | 32 ++++--- .../module/decode/dmr/channel/DMRChannel.java | 89 ++++++++++++++++++- .../module/decode/dmr/channel/DMRLsn.java | 68 +------------- .../decode/dmr/channel/DMRTier3Channel.java | 45 ++-------- .../channel/ITimeslotFrequencyReceiver.java | 4 +- .../decode/dmr/channel/TimeslotFrequency.java | 57 ++++++++++-- .../csbk/motorola/CapacityPlusNeighbors.java | 12 +-- .../csbk/motorola/CapacityPlusSiteStatus.java | 12 +-- .../motorola/ConnectPlusDataChannelGrant.java | 22 ++--- .../motorola/ConnectPlusOTAAnnouncement.java | 22 ++--- .../motorola/ConnectPlusVoiceChannelUser.java | 20 ++--- .../dmr/message/data/csbk/standard/Clear.java | 19 ++-- .../message/data/csbk/standard/MoveTSCC.java | 3 +- .../announcement/AdjacentSiteInformation.java | 4 +- .../AnnounceChannelFrequency.java | 6 +- .../announcement/AnnounceWithdrawTSCC.java | 4 +- .../standard/announcement/VoteNowAdvice.java | 22 ++--- .../BroadcastTalkgroupVoiceChannelGrant.java | 2 +- .../csbk/standard/grant/ChannelGrant.java | 19 ++-- .../grant/DuplexPrivateDataChannelGrant.java | 2 +- .../grant/DuplexPrivateVoiceChannelGrant.java | 2 +- .../grant/PrivateDataChannelGrant.java | 2 +- .../grant/PrivateVoiceChannelGrant.java | 2 +- .../grant/TalkgroupDataChannelGrant.java | 2 +- .../grant/TalkgroupVoiceChannelGrant.java | 2 +- .../CapacityPlusWideAreaVoiceChannelUser.java | 12 +-- .../lc/shorty/CapacityPlusRestChannel.java | 12 +-- .../module/decode/event/DecodeEventPanel.java | 2 +- 34 files changed, 327 insertions(+), 369 deletions(-) diff --git a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java index e4bc0153..8c901377 100644 --- a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java +++ b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java @@ -23,6 +23,7 @@ import io.github.dsheirer.buffer.INativeBufferProvider; import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest; import io.github.dsheirer.dsp.filter.design.FilterDesignException; import io.github.dsheirer.eventbus.MyEventBus; +import io.github.dsheirer.log.LoggingSuppressor; import io.github.dsheirer.sample.Broadcaster; import io.github.dsheirer.sample.Listener; import io.github.dsheirer.sample.complex.InterleavedComplexSamples; @@ -65,6 +66,7 @@ import org.slf4j.LoggerFactory; public class PolyphaseChannelManager implements ISourceEventProcessor { 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 static final double MINIMUM_CHANNEL_BANDWIDTH = 25000.0; private static final double CHANNEL_OVERSAMPLING = 2.0; @@ -203,7 +205,8 @@ public class PolyphaseChannelManager implements ISourceEventProcessor } 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; } } diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java index 5fa5b352..c0bfbc78 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java @@ -85,7 +85,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor private ToggleSwitch mUseCompressedTalkgroupsToggle; private Spinner mTrafficChannelPoolSizeSpinner; private TableView mTimeslotFrequencyTable; - private IntegerTextField mLogicalSlotNumberField; + private IntegerTextField mLogicalChannelNumberField; private FrequencyField mDownlinkFrequencyField; // private FrequencyField mUplinkFrequencyField; private Button mAddTimeslotFrequencyButton; @@ -172,7 +172,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor GridPane.setConstraints(useCompressedTalkgroupsLabel, 7, row); 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.setConstraints(timeslotTableLabel, 0, ++row, 6, 1); gridPane.getChildren().add(timeslotTableLabel); @@ -194,17 +194,13 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor editorBox.setAlignment(Pos.CENTER_LEFT); editorBox.setSpacing(5); - Label lsnLabel = new Label("LSN"); - editorBox.getChildren().addAll(lsnLabel,getLogicalSlotNumberField()); + Label lcnLabel = new Label("LCN"); + editorBox.getChildren().addAll(lcnLabel, getLogicalChannelNumberField()); Label downlinkLabel = new Label("Frequency (MHz)"); downlinkLabel.setPadding(new Insets(0,0,0,5)); 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.getChildren().add(editorBox); @@ -287,20 +283,22 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor mTimeslotFrequencyTable = new TableView<>(FXCollections.observableArrayList(TimeslotFrequency.extractor())); mTimeslotFrequencyTable.setPrefHeight(100.0); - TableColumn numberColumn = new TableColumn("LSN"); - numberColumn.setPrefWidth(70); + TableColumn numberColumn = new TableColumn("LCN"); + numberColumn.setPrefWidth(75); numberColumn.setCellValueFactory(cellData -> cellData.getValue().getNumberProperty()); mTimeslotFrequencyTable.getColumns().addAll(numberColumn); mTimeslotFrequencyTable.getSortOrder().add(numberColumn); TableColumn downlinkColumn = new TableColumn("Frequency (MHz)"); downlinkColumn.setCellValueFactory(cellData -> cellData.getValue().getDownlinkMHz()); - downlinkColumn.setPrefWidth(175); + downlinkColumn.setPrefWidth(150); mTimeslotFrequencyTable.getColumns().addAll(downlinkColumn); -// TableColumn uplinkColumn = new TableColumn("Uplink (MHz)"); -// uplinkColumn.setCellValueFactory(cellData -> cellData.getValue().getUplinkMHz()); -// mTimeslotFrequencyTable.getColumns().addAll(uplinkColumn); + TableColumn lsnColumn = new TableColumn("IDs (TS1/TS2)"); + lsnColumn.setPrefWidth(225); + lsnColumn.setCellValueFactory(new PropertyValueFactory<>("logicalSlotNumbers")); + mTimeslotFrequencyTable.getColumns().addAll(lsnColumn); + mTimeslotFrequencyTable.getSelectionModel().selectedItemProperty() .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. boolean modified = modifiedProperty().get(); - getLogicalSlotNumberField().setDisable(timeslot == null); + getLogicalChannelNumberField().setDisable(timeslot == null); getDownlinkFrequencyField().setDisable(timeslot == null); // getUplinkFrequencyField().setDisable(timeslot == null); getDeleteTimeslotFrequencyButton().setDisable(timeslot == null); if(timeslot != null) { - getLogicalSlotNumberField().set(timeslot.getNumber()); + getLogicalChannelNumberField().set(timeslot.getNumber()); getDownlinkFrequencyField().set(timeslot.getDownlinkFrequency()); // getUplinkFrequencyField().set(timeslot.getUplinkFrequency()); } else { - getLogicalSlotNumberField().set(0); + getLogicalChannelNumberField().set(0); getDownlinkFrequencyField().set(0); // getUplinkFrequencyField().set(0); } @@ -412,19 +410,19 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor return mDeleteTimeslotFrequencyButton; } - private IntegerTextField getLogicalSlotNumberField() + private IntegerTextField getLogicalChannelNumberField() { - if(mLogicalSlotNumberField == null) + if(mLogicalChannelNumberField == null) { - mLogicalSlotNumberField = new IntegerTextField(); - mLogicalSlotNumberField.setDisable(true); - mLogicalSlotNumberField.setPrefWidth(65); - mLogicalSlotNumberField.textProperty().addListener((observable, oldValue, newValue) -> { + mLogicalChannelNumberField = new IntegerTextField(); + mLogicalChannelNumberField.setDisable(true); + mLogicalChannelNumberField.setPrefWidth(65); + mLogicalChannelNumberField.textProperty().addListener((observable, oldValue, newValue) -> { TimeslotFrequency selected = getTimeslotTable().getSelectionModel().getSelectedItem(); if(selected != null) { - Integer value = mLogicalSlotNumberField.get(); + Integer value = mLogicalChannelNumberField.get(); if(value != null) { @@ -436,7 +434,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor }); } - return mLogicalSlotNumberField; + return mLogicalChannelNumberField; } private FrequencyField getDownlinkFrequencyField() @@ -610,8 +608,8 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor getTimeslotTable().setDisable(config == null); getAddTimeslotFrequencyButton().setDisable(config == null); getDeleteTimeslotFrequencyButton().setDisable(true); - getLogicalSlotNumberField().set(0); - getLogicalSlotNumberField().setDisable(true); + getLogicalChannelNumberField().set(0); + getLogicalChannelNumberField().setDisable(true); getDownlinkFrequencyField().set(0); getDownlinkFrequencyField().setDisable(true); // getUplinkFrequencyField().set(0); diff --git a/src/main/java/io/github/dsheirer/gui/playlist/radioreference/RadioReferenceDecoder.java b/src/main/java/io/github/dsheirer/gui/playlist/radioreference/RadioReferenceDecoder.java index 9027d967..d0eb7b95 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/radioreference/RadioReferenceDecoder.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/radioreference/RadioReferenceDecoder.java @@ -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 * 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.Type; import io.github.dsheirer.rrapi.type.Voice; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.Collections; import java.util.List; 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. @@ -374,16 +373,10 @@ public class RadioReferenceDecoder } } - int lsn = (lcn - 1) * 2 + 1; - TimeslotFrequency timeslot1Frequency = new TimeslotFrequency(); - timeslot1Frequency.setNumber(lsn); - timeslot1Frequency.setDownlinkFrequency((long)(siteFrequency.getFrequency() * 1E6)); - frequencies.add(timeslot1Frequency); - - TimeslotFrequency timeslot2Frequency = new TimeslotFrequency(); - timeslot2Frequency.setNumber(lsn + 1); - timeslot2Frequency.setDownlinkFrequency((long)(siteFrequency.getFrequency() * 1E6)); - frequencies.add(timeslot2Frequency); + TimeslotFrequency timeslotFrequency = new TimeslotFrequency(); + timeslotFrequency.setNumber(lcn); + timeslotFrequency.setDownlinkFrequency((long)(siteFrequency.getFrequency() * 1E6)); + frequencies.add(timeslotFrequency); } return frequencies; diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java index 5cc33f1d..6d1fdf3c 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java @@ -90,9 +90,9 @@ import io.github.dsheirer.module.decode.ip.mototrbo.xcmp.XCMPPacket; import io.github.dsheirer.protocol.Protocol; import io.github.dsheirer.source.tuner.channel.rotation.AddChannelRotationActiveStateRequest; import io.github.dsheirer.util.PacketUtil; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.TreeMap; import org.jdesktop.swingx.mapviewer.GeoPosition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -111,7 +111,7 @@ public class DMRDecoderState extends TimeslotDecoderState private DecodeEvent mCurrentCallEvent; private long mCurrentFrequency; private boolean mIgnoreCRCChecksums; - private Map mDetectedCallEventsMap = new TreeMap<>(); + private Map mDetectedCallEventsMap = new HashMap<>(); private static final AddChannelRotationActiveStateRequest CAPACITY_PLUS_ACTIVE_STATE_REQUEST = new AddChannelRotationActiveStateRequest(State.ACTIVE); @@ -417,7 +417,7 @@ public class DMRDecoderState extends TimeslotDecoderState else { DecodeEvent packetEvent = DMRDecodeEvent.builder(DecodeEventType.DATA_PACKET, packet.getTimestamp()) - .identifiers(getMergedIdentifierCollection(packet.getIdentifiers())) + .identifiers(new IdentifierCollection(packet.getIdentifiers())) .timeslot(getTimeslot()) .details(packet.toString()) .build(); @@ -429,7 +429,7 @@ public class DMRDecoderState extends TimeslotDecoderState if (geoPosition != null) { PlottableDecodeEvent plottableDecodeEvent = PlottableDecodeEvent.plottableBuilder(DecodeEventType.GPS, packet.getTimestamp()) .channel(getCurrentChannel()) - .identifiers(getMergedIdentifierCollection(packet.getIdentifiers())) + .identifiers(new IdentifierCollection(packet.getIdentifiers())) .protocol(Protocol.LRRP) .location(geoPosition) .build(); @@ -735,21 +735,22 @@ public class DMRDecoderState extends TimeslotDecoderState ChannelGrant dataGrant = (ChannelGrant)csbk; DMRChannel channel = dataGrant.getChannel(); - IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers()); if(hasTrafficChannelManager()) { + IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers()); mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(), csbk.getTimestamp(), csbk.isEncrypted()); } else { - DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue()); + DecodeEvent event = mDetectedCallEventsMap.get(channel); if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers())) { - event = getDecodeEvent(csbk, DecodeEventType.DATA_CALL, channel, mergedIdentifiers); - mDetectedCallEventsMap.put(channel.getValue(), event); + event = getDecodeEvent(csbk, DecodeEventType.DATA_CALL, channel, + new IdentifierCollection(csbk.getIdentifiers())); + mDetectedCallEventsMap.put(channel, event); } else { @@ -768,21 +769,22 @@ public class DMRDecoderState extends TimeslotDecoderState ChannelGrant tgGrant = (ChannelGrant)csbk; DMRChannel channel = tgGrant.getChannel(); - IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers()); - if(hasTrafficChannelManager()) { + IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers()); + mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(), csbk.getTimestamp(), csbk.isEncrypted()); } else { - DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue()); + DecodeEvent event = mDetectedCallEventsMap.get(channel); if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers())) { - event = getDecodeEvent(csbk, DecodeEventType.CALL_GROUP, channel, mergedIdentifiers); - mDetectedCallEventsMap.put(channel.getValue(), event); + event = getDecodeEvent(csbk, DecodeEventType.CALL_GROUP, channel, + new IdentifierCollection(csbk.getIdentifiers())); + mDetectedCallEventsMap.put(channel, event); } else { @@ -800,21 +802,23 @@ public class DMRDecoderState extends TimeslotDecoderState { ChannelGrant channelGrant = (ChannelGrant)csbk; DMRChannel channel = channelGrant.getChannel(); - IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers()); if(hasTrafficChannelManager()) { + IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers()); + mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(), csbk.getTimestamp(), csbk.isEncrypted()); } else { - DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue()); + DecodeEvent event = mDetectedCallEventsMap.get(channel); if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers())) { - event = getDecodeEvent(csbk, DecodeEventType.CALL_UNIT_TO_UNIT, channel, mergedIdentifiers); - mDetectedCallEventsMap.put(channel.getValue(), event); + event = getDecodeEvent(csbk, DecodeEventType.CALL_UNIT_TO_UNIT, channel, + new IdentifierCollection(csbk.getIdentifiers())); + mDetectedCallEventsMap.put(channel, event); } else { @@ -845,21 +849,22 @@ public class DMRDecoderState extends TimeslotDecoderState ConnectPlusDataChannelGrant cpdcg = (ConnectPlusDataChannelGrant)csbk; DMRChannel channel = cpdcg.getChannel(); - IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers()); - if(hasTrafficChannelManager()) { + IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers()); + mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(), csbk.getTimestamp(), csbk.isEncrypted()); } else { - DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue()); + DecodeEvent event = mDetectedCallEventsMap.get(channel); if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers())) { - event = getDecodeEvent(csbk, DecodeEventType.DATA_CALL, channel, mergedIdentifiers); - mDetectedCallEventsMap.put(channel.getValue(), event); + event = getDecodeEvent(csbk, DecodeEventType.DATA_CALL, channel, + new IdentifierCollection(csbk.getIdentifiers())); + mDetectedCallEventsMap.put(channel, event); } else { @@ -875,7 +880,7 @@ public class DMRDecoderState extends TimeslotDecoderState case MOTOROLA_CONPLUS_REGISTRATION_REQUEST: DecodeEvent event = DMRDecodeEvent.builder(DecodeEventType.REQUEST, csbk.getTimestamp()) .details("Registration Request") - .identifiers(getMergedIdentifierCollection(csbk.getIdentifiers())) + .identifiers(new IdentifierCollection(csbk.getIdentifiers())) .timeslot(getTimeslot()) .build(); broadcast(event); @@ -884,7 +889,7 @@ public class DMRDecoderState extends TimeslotDecoderState case MOTOROLA_CONPLUS_REGISTRATION_RESPONSE: DecodeEvent regRespEvent = DMRDecodeEvent.builder(DecodeEventType.RESPONSE, csbk.getTimestamp()) .details("Registration Response") - .identifiers(getMergedIdentifierCollection(csbk.getIdentifiers())) + .identifiers(new IdentifierCollection(csbk.getIdentifiers())) .timeslot(getTimeslot()) .build(); broadcast(regRespEvent); @@ -896,21 +901,22 @@ public class DMRDecoderState extends TimeslotDecoderState ConnectPlusVoiceChannelUser cpvcu = (ConnectPlusVoiceChannelUser)csbk; DMRChannel channel = cpvcu.getChannel(); - IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers()); - if(hasTrafficChannelManager()) { + IdentifierCollection mergedIdentifiers = getMergedIdentifierCollection(csbk.getIdentifiers()); + mTrafficChannelManager.processChannelGrant(channel, mergedIdentifiers, csbk.getOpcode(), csbk.getTimestamp(), csbk.isEncrypted()); } else { - DecodeEvent detectedEvent = mDetectedCallEventsMap.get(channel.getValue()); + DecodeEvent detectedEvent = mDetectedCallEventsMap.get(channel); if(isStale(detectedEvent, csbk.getTimestamp(), csbk.getIdentifiers())) { - detectedEvent = getDecodeEvent(csbk, DecodeEventType.CALL_GROUP, channel, mergedIdentifiers); - mDetectedCallEventsMap.put(channel.getValue(), detectedEvent); + detectedEvent = getDecodeEvent(csbk, DecodeEventType.CALL_GROUP, channel, + new IdentifierCollection(csbk.getIdentifiers())); + mDetectedCallEventsMap.put(channel, detectedEvent); } else { @@ -926,7 +932,7 @@ public class DMRDecoderState extends TimeslotDecoderState case MOTOROLA_CONPLUS_TALKGROUP_AFFILIATION: DecodeEvent affiliateEvent = DMRDecodeEvent.builder(DecodeEventType.AFFILIATE, csbk.getTimestamp()) .details("TALKGROUP AFFILIATION") - .identifiers(getMergedIdentifierCollection(csbk.getIdentifiers())) + .identifiers(new IdentifierCollection(csbk.getIdentifiers())) .timeslot(getTimeslot()) .build(); broadcast(affiliateEvent); @@ -939,18 +945,18 @@ public class DMRDecoderState extends TimeslotDecoderState } private DecodeEvent getDecodeEvent(CSBKMessage csbk, DecodeEventType decodeEventType, DMRChannel channel, - IdentifierCollection mergedIdentifiers) { + IdentifierCollection identifierCollection) { return DMRDecodeEvent.builder(decodeEventType, csbk.getTimestamp()) .channel(channel) .details(csbk.getOpcode().getLabel()) - .identifiers(mergedIdentifiers) + .identifiers(identifierCollection) .timeslot(getTimeslot()) .build(); } private DecodeEvent getDecodeEvent(CSBKMessage csbk, DecodeEventType decodeEventType, String details) { return DMRDecodeEvent.builder(decodeEventType, csbk.getTimestamp()) - .identifiers(getMergedIdentifierCollection(csbk.getIdentifiers())) + .identifiers(new IdentifierCollection(csbk.getIdentifiers())) .timeslot(getTimeslot()) .details(details) .build(); diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java index 97a9f367..c3a6f459 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java @@ -127,19 +127,19 @@ public class DMRMessageProcessor implements Listener } } - //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) { ITimeslotFrequencyReceiver receiver = (ITimeslotFrequencyReceiver)message; - int[] lsns = receiver.getLogicalSlotNumbers(); + int[] lcns = receiver.getLogicalChannelNumbers(); List 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)); } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRNetworkConfigurationMonitor.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRNetworkConfigurationMonitor.java index 857d46f7..8ce21167 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRNetworkConfigurationMonitor.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRNetworkConfigurationMonitor.java @@ -1,23 +1,20 @@ /* + * ***************************************************************************** + * Copyright (C) 2014-2023 Dennis Sheirer * - * * ****************************************************************************** - * * Copyright (C) 2014-2020 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** + * 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 + * **************************************************************************** */ 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.type.Model; 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.Collections; import java.util.HashMap; import java.util.List; 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 @@ -250,7 +246,7 @@ public class DMRNetworkConfigurationMonitor ConnectPlusNeighborReport cpnr = (ConnectPlusNeighborReport)csbk; mNeighborSites.addAll(cpnr.getNeighbors()); } - if(mBrand == null) + if(mBrand == null || mBrand != BRAND_MOTOROLA_CONNECT_PLUS) { mBrand = BRAND_MOTOROLA_CONNECT_PLUS; } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRTrafficChannelManager.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRTrafficChannelManager.java index 3b64a8e8..9d0e18dd 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRTrafficChannelManager.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRTrafficChannelManager.java @@ -98,7 +98,7 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I private List mManagedTrafficChannels; private Map mAllocatedTrafficChannelFrequencyMap = new ConcurrentHashMap<>(); - private Map mLSNGrantEventMap = new ConcurrentHashMap<>(); + private Map mChannelGrantEventMap = new ConcurrentHashMap<>(); private Listener mChannelEventListener; private Listener mDecodeEventListener; @@ -322,9 +322,7 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I public void processChannelGrant(DMRChannel channel, IdentifierCollection identifierCollection, Opcode opcode, long timestamp, boolean encrypted) { - int lsn = channel.getValue(); - - DMRChannelGrantEvent event = mLSNGrantEventMap.get(lsn); + DMRChannelGrantEvent event = mChannelGrantEventMap.get(channel); DecodeEventType decodeEventType = getEventType(opcode, identifierCollection, encrypted); if(isStale(event, timestamp, identifierCollection)) //Create new event @@ -335,7 +333,7 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I .identifiers(identifierCollection) .build(); - mLSNGrantEventMap.put(lsn, event); + mChannelGrantEventMap.put(channel, event); } else //Update current event @@ -355,7 +353,7 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I .identifiers(identifierCollection) .build(); - mLSNGrantEventMap.put(lsn, event); + mChannelGrantEventMap.put(channel, event); broadcast(event); } } @@ -643,37 +641,37 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I */ private void removeCallEvents(long frequency) { - List lsnsToRemove = new ArrayList<>(); + List channelsToRemove = new ArrayList<>(); - for(Map.Entry entry: mLSNGrantEventMap.entrySet()) + for(Map.Entry 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) { - List lsnsToUpdate = new ArrayList<>(); + List channelsToUpdate = new ArrayList<>(); - for(Map.Entry entry: mLSNGrantEventMap.entrySet()) + for(Map.Entry entry: mChannelGrantEventMap.entrySet()) { 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) { diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRChannel.java b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRChannel.java index e4653a2c..cc2040c9 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRChannel.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRChannel.java @@ -26,6 +26,8 @@ import io.github.dsheirer.identifier.Role; import io.github.dsheirer.identifier.integer.IntegerIdentifier; import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBand; import io.github.dsheirer.protocol.Protocol; +import java.util.List; +import java.util.Objects; import org.apache.commons.lang3.Validate; /** @@ -33,8 +35,9 @@ import org.apache.commons.lang3.Validate; * * 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; /** @@ -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(); } + /** + * 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. * @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 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"); } + + @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 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()); + } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRLsn.java b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRLsn.java index 1cb9c5a8..ceb74c33 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRLsn.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRLsn.java @@ -19,8 +19,6 @@ package io.github.dsheirer.module.decode.dmr.channel; -import java.util.List; - /** * DMR Logical Slot Number (LSN) channel. * @@ -44,10 +42,8 @@ import java.util.List; * 15: 8/1 * 16: 8/2 */ -public class DMRLsn extends DMRChannel implements ITimeslotFrequencyReceiver +public class DMRLsn extends DMRChannel { - private TimeslotFrequency mTimeslotFrequency; - /** * Constructs an instance * @@ -61,7 +57,7 @@ public class DMRLsn extends DMRChannel implements ITimeslotFrequencyReceiver @Override 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() { - 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 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); - } - } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRTier3Channel.java b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRTier3Channel.java index 3955bc46..b14b2a10 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRTier3Channel.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRTier3Channel.java @@ -24,14 +24,12 @@ package io.github.dsheirer.module.decode.dmr.channel; */ 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 * calculated logical slot value for visual compatibility for users. * * @param channel number or repeater number - * @param logicalSlotNumber - zero based index. + * @param timeslot either 1 or 2. */ public DMRTier3Channel(int channel, int timeslot) { @@ -39,42 +37,12 @@ public class DMRTier3Channel extends DMRChannel } /** - * Downlink frequency - * @return value in Hertz, or 0 if this channel doesn't have a timeslot frequency mapping + * Tier III Channel ID + * @return channel ID */ - @Override - public long getDownlinkFrequency() + public int getChannelId() { - if(mTimeslotFrequency != null) - { - 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; + return getChannelNumber() * 2 + getTimeslot(); } /** @@ -83,7 +51,8 @@ public class DMRTier3Channel extends DMRChannel public String toString() { StringBuilder sb = new StringBuilder(); - sb.append(" LCN:").append(getValue()); + sb.append(" LCN:").append(getChannelNumber()); + sb.append(" CHANID:").append(getChannelId()); return sb.toString(); } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/ITimeslotFrequencyReceiver.java b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/ITimeslotFrequencyReceiver.java index fffd1541..50f5b9bd 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/ITimeslotFrequencyReceiver.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/ITimeslotFrequencyReceiver.java @@ -24,9 +24,9 @@ import java.util.List; 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 diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/TimeslotFrequency.java b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/TimeslotFrequency.java index 1a5a4e81..a83d730e 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/TimeslotFrequency.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/TimeslotFrequency.java @@ -31,7 +31,7 @@ import javafx.beans.property.SimpleLongProperty; 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 { @@ -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") public int getNumber() @@ -109,12 +112,52 @@ public class TimeslotFrequency } /** - * Sets the logical slot number (LSN) as a 1-index start - * @param lsn where LSN 1 is the first slot, 2 the second, etc + * Logical channel number which is the same value as getNumber. + * @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 public String toString() { - return "TIMESLOT LSN:" + getNumber() + " DOWNLINK:" + getDownlinkFrequency(); + return "LCN:" + getNumber() + " DOWNLINK:" + getDownlinkFrequency(); } /** diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusNeighbors.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusNeighbors.java index 409d10ba..c228ae9b 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusNeighbors.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusNeighbors.java @@ -299,9 +299,9 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ } @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 public void apply(List timeslotFrequencies) { - for(TimeslotFrequency timeslotFrequency : timeslotFrequencies) - { - if(timeslotFrequency.getNumber() == getRestChannel().getValue()) - { - getRestChannel().setTimeslotFrequency(timeslotFrequency); - } - } + getRestChannel().apply(timeslotFrequencies); } @Override diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSiteStatus.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSiteStatus.java index d42a4954..6a7c7651 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSiteStatus.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSiteStatus.java @@ -299,9 +299,9 @@ public class CapacityPlusSiteStatus extends CSBKMessage implements ITimeslotFreq * Logical slot numbers that require slot to frequency mappings. */ @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 public void apply(List timeslotFrequencies) { - for(TimeslotFrequency timeslotFrequency : timeslotFrequencies) - { - if(getRestChannel().getValue() == timeslotFrequency.getNumber()) - { - getRestChannel().setTimeslotFrequency(timeslotFrequency); - } - } + getRestChannel().apply(timeslotFrequencies); } @Override diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataChannelGrant.java index b2e56521..dedd64f9 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataChannelGrant.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataChannelGrant.java @@ -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, 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. 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) { - mDmrLsn = new DMRLsn(getRepeater()); + mDmrLsn = new DMRLsn(getLsn()); } return mDmrLsn; } @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 public void apply(List timeslotFrequencies) { - for(TimeslotFrequency timeslotFrequency: timeslotFrequencies) - { - if(timeslotFrequency.getNumber() == getChannel().getValue()) - { - getChannel().setTimeslotFrequency(timeslotFrequency); - } - } + getChannel().apply(timeslotFrequencies); } @Override diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusOTAAnnouncement.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusOTAAnnouncement.java index a886be8e..1da6ac4a 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusOTAAnnouncement.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusOTAAnnouncement.java @@ -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[] 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}; - 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 List 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) { - mDataChannel = new DMRLsn(getDataRepeater()); + mDataChannel = new DMRLsn(getDataLsn()); } return mDataChannel; } @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 public void apply(List timeslotFrequencies) { - for(TimeslotFrequency timeslotFrequency : timeslotFrequencies) - { - if(timeslotFrequency.getNumber() == getDataChannel().getValue()) - { - getDataChannel().setTimeslotFrequency(timeslotFrequency); - } - } + getDataChannel().apply(timeslotFrequencies); } @Override diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusVoiceChannelUser.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusVoiceChannelUser.java index ea674163..e09ca5d3 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusVoiceChannelUser.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusVoiceChannelUser.java @@ -44,7 +44,7 @@ public class ConnectPlusVoiceChannelUser extends CSBKMessage implements ITimeslo 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, 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 RadioIdentifier mRadio; @@ -126,9 +126,9 @@ public class ConnectPlusVoiceChannelUser extends CSBKMessage implements ITimeslo /** * 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) { - mDmrLsn = new DMRLsn(getTrafficChannelRepeater()); + mDmrLsn = new DMRLsn(getTrafficLsn()); } return mDmrLsn; } @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 public void apply(List timeslotFrequencies) { - for(TimeslotFrequency timeslotFrequency: timeslotFrequencies) - { - if(timeslotFrequency.getNumber() == getChannel().getValue()) - { - getChannel().setTimeslotFrequency(timeslotFrequency); - } - } + getChannel().apply(timeslotFrequencies); } @Override diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Clear.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Clear.java index d99632c1..b84ebd24 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Clear.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Clear.java @@ -25,7 +25,6 @@ import io.github.dsheirer.identifier.integer.IntegerIdentifier; import io.github.dsheirer.identifier.radio.RadioIdentifier; 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.DMRLsn; 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.TimeslotFrequency; @@ -224,11 +223,11 @@ public class Clear extends CSBKMessage implements ITimeslotFrequencyReceiver * Logical Slot Number(s) for channels contained in this message */ @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]; @@ -241,17 +240,9 @@ public class Clear extends CSBKMessage implements ITimeslotFrequencyReceiver @Override public void apply(List timeslotFrequencies) { - if(getMoveToChannel() instanceof DMRTier3Channel) + if(getMoveToChannel() != null) { - DMRTier3Channel channel = (DMRTier3Channel)getMoveToChannel(); - - for(TimeslotFrequency timeslotFrequency: timeslotFrequencies) - { - if(channel.getValue() == timeslotFrequency.getNumber()) - { - channel.setTimeslotFrequency(timeslotFrequency); - } - } + getMoveToChannel().apply(timeslotFrequencies); } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/MoveTSCC.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/MoveTSCC.java index b8c791c8..d3579412 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/MoveTSCC.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/MoveTSCC.java @@ -88,7 +88,8 @@ public class MoveTSCC extends CSBKMessage 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); } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AdjacentSiteInformation.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AdjacentSiteInformation.java index 73121bde..3baae713 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AdjacentSiteInformation.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AdjacentSiteInformation.java @@ -84,8 +84,8 @@ public class AdjacentSiteInformation extends Announcement if(multiBlock != null) { - //Timeslot hard-coded to zero for control channel - mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 0); + //Timeslot hard-coded to one for control channel + mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 1); } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AnnounceChannelFrequency.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AnnounceChannelFrequency.java index bdbedeb1..3213f402 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AnnounceChannelFrequency.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AnnounceChannelFrequency.java @@ -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 * 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.type.AbsoluteChannelParameters; import io.github.dsheirer.module.decode.dmr.message.type.DataType; - import java.util.ArrayList; import java.util.List; @@ -56,7 +55,8 @@ public class AnnounceChannelFrequency extends Announcement if(multiBlock != null) { - mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 0); + //Timeslot hard-coded to one + mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 1); } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AnnounceWithdrawTSCC.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AnnounceWithdrawTSCC.java index b1674fde..99a09bb3 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AnnounceWithdrawTSCC.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/AnnounceWithdrawTSCC.java @@ -86,8 +86,8 @@ public class AnnounceWithdrawTSCC extends Announcement if(multiBlock != null) { - //Control channel timeslot hard-coded to 0 - mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 0); + //Control channel timeslot hard-coded to 1 + mAbsoluteChannelParameters = new AbsoluteChannelParameters(multiBlock.getMessage(), 0, 1); } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/VoteNowAdvice.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/VoteNowAdvice.java index c0c5c6da..5850895b 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/VoteNowAdvice.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/VoteNowAdvice.java @@ -23,7 +23,6 @@ import io.github.dsheirer.bits.CorrectedBinaryMessage; import io.github.dsheirer.identifier.Identifier; 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.DMRLsn; 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.TimeslotFrequency; @@ -90,7 +89,8 @@ public class VoteNowAdvice extends Announcement implements ITimeslotFrequencyRec 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 */ @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]; @@ -256,17 +256,9 @@ public class VoteNowAdvice extends Announcement implements ITimeslotFrequencyRec @Override public void apply(List timeslotFrequencies) { - if(getChannel() instanceof DMRTier3Channel) + if(getChannel() != null) { - DMRTier3Channel channel = (DMRTier3Channel)getChannel(); - - for(TimeslotFrequency timeslotFrequency: timeslotFrequencies) - { - if(channel.getValue() == timeslotFrequency.getNumber()) - { - channel.setTimeslotFrequency(timeslotFrequency); - } - } + getChannel().apply(timeslotFrequencies); } } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/BroadcastTalkgroupVoiceChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/BroadcastTalkgroupVoiceChannelGrant.java index 859bf907..dff50189 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/BroadcastTalkgroupVoiceChannelGrant.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/BroadcastTalkgroupVoiceChannelGrant.java @@ -104,7 +104,7 @@ public class BroadcastTalkgroupVoiceChannelGrant extends ChannelGrant sb.append(" BROADCAST TALKGROUP VOICE CHANNEL GRANT FM:").append(getSourceRadio()); sb.append(" TO:").append(getDestinationTalkgroup()); - sb.append(" CHAN:").append(getChannel()); + sb.append(" ").append(getChannel()); return sb.toString(); } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/ChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/ChannelGrant.java index 6229430e..55578103 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/ChannelGrant.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/ChannelGrant.java @@ -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.module.decode.dmr.DMRSyncPattern; 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.ITimeslotFrequencyReceiver; 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 */ @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]; @@ -175,17 +174,9 @@ public abstract class ChannelGrant extends CSBKMessage implements ITimeslotFrequ @Override public void apply(List timeslotFrequencies) { - if(getChannel() instanceof DMRTier3Channel) + if(getChannel() != null) { - DMRTier3Channel channel = (DMRTier3Channel)getChannel(); - - for(TimeslotFrequency timeslotFrequency: timeslotFrequencies) - { - if(channel.getValue() == timeslotFrequency.getNumber()) - { - channel.setTimeslotFrequency(timeslotFrequency); - } - } + getChannel().apply(timeslotFrequencies); } } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateDataChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateDataChannelGrant.java index 5b68cb9a..6e42736a 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateDataChannelGrant.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateDataChannelGrant.java @@ -103,7 +103,7 @@ public class DuplexPrivateDataChannelGrant extends ChannelGrant sb.append(" DUPLEX PRIVATE DATA CHANNEL GRANT FM:").append(getSourceRadio()); sb.append(" TO:").append(getDestinationRadio()); - sb.append(" CHAN:").append(getChannel()); + sb.append(" ").append(getChannel()); return sb.toString(); } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateVoiceChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateVoiceChannelGrant.java index eab51690..c9fdcca7 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateVoiceChannelGrant.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateVoiceChannelGrant.java @@ -103,7 +103,7 @@ public class DuplexPrivateVoiceChannelGrant extends ChannelGrant sb.append(" DUPLEX PRIVATE VOICE CHANNEL GRANT FM:").append(getSourceRadio()); sb.append(" TO:").append(getDestinationRadio()); - sb.append(" CHAN:").append(getChannel()); + sb.append(" ").append(getChannel()); return sb.toString(); } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateDataChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateDataChannelGrant.java index 58400f5d..f643f66e 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateDataChannelGrant.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateDataChannelGrant.java @@ -108,7 +108,7 @@ public class PrivateDataChannelGrant extends ChannelGrant sb.append(" PRIVATE DATA CHANNEL GRANT FM:").append(getSourceRadio()); sb.append(" TO:").append(getDestinationRadio()); - sb.append(" CHAN:").append(getChannel()); + sb.append(" ").append(getChannel()); return sb.toString(); } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateVoiceChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateVoiceChannelGrant.java index 74492622..d6888909 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateVoiceChannelGrant.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateVoiceChannelGrant.java @@ -102,7 +102,7 @@ public class PrivateVoiceChannelGrant extends ChannelGrant sb.append(" PRIVATE VOICE CHANNEL GRANT FM:").append(getSourceRadio()); sb.append(" TO:").append(getDestinationRadio()); - sb.append(" CHAN:").append(getChannel()); + sb.append(" ").append(getChannel()); return sb.toString(); } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupDataChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupDataChannelGrant.java index 49e54257..e44f46a8 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupDataChannelGrant.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupDataChannelGrant.java @@ -110,7 +110,7 @@ public class TalkgroupDataChannelGrant extends ChannelGrant sb.append(" TALKGROUP DATA CHANNEL GRANT FM:").append(getSourceRadio()); sb.append(" TO:").append(getDestinationTalkgroup()); - sb.append(" CHAN:").append(getChannel()); + sb.append(" ").append(getChannel()); return sb.toString(); } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupVoiceChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupVoiceChannelGrant.java index 3406e685..a52526ba 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupVoiceChannelGrant.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupVoiceChannelGrant.java @@ -104,7 +104,7 @@ public class TalkgroupVoiceChannelGrant extends ChannelGrant sb.append(" TALKGROUP VOICE CHANNEL GRANT FM:").append(getSourceRadio()); sb.append(" TO:").append(getDestinationTalkgroup()); - sb.append(" CHAN:").append(getChannel()); + sb.append(" ").append(getChannel()); return sb.toString(); } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/full/motorola/CapacityPlusWideAreaVoiceChannelUser.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/full/motorola/CapacityPlusWideAreaVoiceChannelUser.java index f44af10e..25e38f83 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/full/motorola/CapacityPlusWideAreaVoiceChannelUser.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/full/motorola/CapacityPlusWideAreaVoiceChannelUser.java @@ -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. */ @Override - public int[] getLogicalSlotNumbers() + public int[] getLogicalChannelNumbers() { - return getRestChannel().getLogicalSlotNumbers(); + return getRestChannel().getLogicalChannelNumbers(); } /** @@ -189,12 +189,6 @@ public class CapacityPlusWideAreaVoiceChannelUser extends CapacityPlusVoiceChann @Override public void apply(List timeslotFrequencies) { - for(TimeslotFrequency timeslotFrequency : timeslotFrequencies) - { - if(getRestChannel().getValue() == timeslotFrequency.getNumber()) - { - getRestChannel().setTimeslotFrequency(timeslotFrequency); - } - } + getRestChannel().apply(timeslotFrequencies); } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/shorty/CapacityPlusRestChannel.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/shorty/CapacityPlusRestChannel.java index b3e3e893..51e79fa2 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/shorty/CapacityPlusRestChannel.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/shorty/CapacityPlusRestChannel.java @@ -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. */ @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 public void apply(List timeslotFrequencies) { - for(TimeslotFrequency timeslotFrequency: timeslotFrequencies) - { - if(getRestChannel().getValue() == timeslotFrequency.getNumber()) - { - getRestChannel().setTimeslotFrequency(timeslotFrequency); - } - } + getRestChannel().apply(timeslotFrequencies); } @Override diff --git a/src/main/java/io/github/dsheirer/module/decode/event/DecodeEventPanel.java b/src/main/java/io/github/dsheirer/module/decode/event/DecodeEventPanel.java index 4dcec151..2105d4f4 100644 --- a/src/main/java/io/github/dsheirer/module/decode/event/DecodeEventPanel.java +++ b/src/main/java/io/github/dsheirer/module/decode/event/DecodeEventPanel.java @@ -221,7 +221,7 @@ public class DecodeEventPanel extends JPanel implements Listener