Compare commits

...

46 Commits

Author SHA1 Message Date
Denny Sheirer
8827ecd0e9 Merge pull request #207 from DSheirer/206-alias-list-npe-null-list-name
206 alias list npe null list name
2017-02-24 10:25:29 +00:00
Denny
8660002f93 Incrementing build to beta 6 2017-02-24 05:24:38 -05:00
Denny
2058fcbc1d Resolves issue #206 - alias list throws NPE on aliases that don't have a list name specified. 2017-02-24 05:23:48 -05:00
Denny
9515dfa380 Incrementing build for 0.3.0 beta #5 2017-02-20 20:25:43 -05:00
Denny
9e9a604c6a Merge remote-tracking branch 'origin/master' 2017-02-20 20:20:11 -05:00
Denny
234e313b7a Resolves issue with Null Pointer exception in alias list 2017-02-20 20:19:47 -05:00
Denny Sheirer
e1e7169029 Merge pull request #203 from DSheirer/199-utf8-encoding-of-metadata
Resolves issue with UTF-8 encoding of Shoutcast 2 metadata updates.
2017-02-17 23:09:10 +00:00
Denny
f3605db0ed Resolves issue where metadata is UTF-8 URL encoded versus UTF-8 String encoding. 2017-02-17 18:08:01 -05:00
Denny Sheirer
c0a6d578c7 Merge pull request #202 from DSheirer/201-audio-stream-failed-reconnect
Resolves issue with audio broadcasters attempting to reconnect if a c…
2017-02-17 22:54:58 +00:00
Denny
79b4b30ec7 Resolves issue with audio broadcasters attempting to reconnect if a connection attempt is not successful. 2017-02-17 17:53:42 -05:00
Denny
17c7466c6b Resolves logic issue in Icecast error handling during resets. 2017-02-13 20:51:10 -05:00
Denny Sheirer
8162d6ffd6 Merge pull request #196 from DSheirer/164-patched-group-streaming-duplicates
Resolves #173 - duplicate streaming calls for patch groups.
2017-02-12 15:59:46 +00:00
Denny
cd60251337 Resolves #173 - duplicate streaming calls for patch groups. 2017-02-12 10:59:06 -05:00
Denny Sheirer
5647879b37 Merge pull request #195 from DSheirer/173-p25-tdma-channel-frequencies-incorrect
Resolves #173 - logging/management of  P25 TDMA channels.
2017-02-12 15:21:50 +00:00
Denny
6916d95cdf Resolves #173 - logging/management of P25 TDMA channels. There is no Phase II decoder support yet. 2017-02-12 10:20:45 -05:00
Denny Sheirer
a0c32f6fe0 Merge pull request #194 from DSheirer/193-icecast-tcp-write-timeout-exception
Resolves #193 - adds handling for MINA WriteTimeoutException
2017-02-12 13:05:11 +00:00
Denny
c3d60dc174 Resolves #193 - adds handling for MINA WriteTimeoutException error. Resets connection when this occurs. 2017-02-12 08:04:27 -05:00
Denny Sheirer
e55a2226a2 Merge pull request #192 from DSheirer/189-shoutcast-ultravox-UTF8-encoding
Resolves #189 - add UTF-8 encoding to shoutcast v2
2017-02-12 12:45:10 +00:00
Denny
9f01678b00 Resolves #189 - add UTF-8 encoding to shoutcast v2 (ultravox) XML metadata update values. 2017-02-12 07:43:51 -05:00
Denny Sheirer
46425e9cae Merge pull request #191 from DSheirer/188-p25-activity-summary-cleanup
188 p25 activity summary cleanup
2017-02-12 12:31:45 +00:00
Denny
3726401563 Resolves #188 - cleanup of the P25 and MPT activity summaries. Resolves an issue in the SNDCP downlink/uplink channel frequencies. 2017-02-12 07:30:32 -05:00
Denny
a3e50acfe3 Incrementing build to 0.3.0-beta4 2017-02-11 09:02:35 -05:00
Denny
cf0018e6ba Incrementing build to 0.3.0-beta4 2017-02-11 07:22:54 -05:00
Denny Sheirer
e8055dcab0 Merge pull request #187 from DSheirer/186-p25-c4fm-decoder-no-worky
Resolves #186 - p25 C4FM decoder wasn't working (at all).
2017-02-11 12:17:58 +00:00
Denny
fce3d5c4f3 Resolves #186 - p25 C4FM decoder wasn't working (at all). 2017-02-11 07:17:23 -05:00
Denny Sheirer
9cc0d367a8 Merge pull request #185 from DSheirer/183-alias-list-throws-npe-on-empty-name
Resolves #183 - alias list throws NPE when created with a null or emp…
2017-02-11 00:35:16 +00:00
Denny
2ca9e5d5ce Resolves #183 - alias list throws NPE when created with a null or empty name and receives alias updates. 2017-02-10 19:34:50 -05:00
Denny Sheirer
861203c3a0 Merge pull request #184 from DSheirer/181-patch-group-audio-priority
Resolves #181 - patch group audio priority will assume the highest (l…
2017-02-11 00:31:42 +00:00
Denny
7c930deefe Resolves #181 - patch group audio priority will assume the highest (listenable) audio priority and override a 'Do Not Monitor' setting if any of the other aliases have an audio priority defined. 2017-02-10 19:31:09 -05:00
Denny
0e0af932eb Incrementing build to 0.3.0-beta3 2017-02-10 17:09:54 -05:00
Denny Sheirer
6ba5e91fcb Merge pull request #182 from DSheirer/176-streaming-handle-additional-io-exceptions
Resolves #176 - resolves 2 streaming related issues
2017-02-10 22:06:32 +00:00
Denny
34dd2161ef Resolves #176 - 2 issues:
A) streaming connection errors - detects errors and if currently connected, resets the connection.

B)duplicate calls being streamed - issue with comparison of broadcast channels allowed the same broadcast channel to be queued two or more times for the list of channels to stream a recording.
2017-02-10 17:05:28 -05:00
Denny Sheirer
2543072e08 Merge pull request #180 from DSheirer/166-traffic_channel_manager_cleanup
Resolves #166 - removes traffic channel timeout from traffic channel manager
2017-02-10 15:31:24 +00:00
Denny
281be147f8 Resolves #166 - removes traffic channel timeout from traffic channel manager 2017-02-10 10:30:35 -05:00
Denny Sheirer
12ecca4555 Merge pull request #179 from DSheirer/169-aarch64-usb-support-for-ARM64
Resolves #165 - adds ARM64 (aarch64) linux libusb support
2017-02-10 15:26:16 +00:00
Denny
4c27d04120 Resolves #165 - adds ARM64 (aarch64) linux libusb support 2017-02-10 10:08:52 -05:00
Denny Sheirer
ece202315f Merge pull request #178 from DSheirer/165-overflowable-buffer-issue-causes-channels-decoding-stop
165 overflowable buffer issue causes channels decoding stop
2017-02-10 14:50:30 +00:00
Denny Sheirer
6afe5dcec9 Merge pull request #177 from DSheirer/master
165 - P25 Channel stops decoding
2017-02-10 14:47:33 +00:00
Denny
8db47c25bc #165 - cleanup of logging and comments in TunerChannelSource 2017-02-10 09:45:32 -05:00
Denny
6a340050c6 #165 - cleanup of logging and comments in TunerChannelSource 2017-02-10 06:41:45 -05:00
Denny
183eb2f7c7 Resolves #165 - P25 decoding channel stops arbitrarily and never recovers.
Issue identified with Patch Group management and circular dependencies that can develop because of stale patch groups.  Refactored all patch group management into a new PatchGroupManager.  Patch groups are now automatically deleted if we don't receive any update messages within 5 seconds.  The PatchGroupAlias was also updated to not roll-up attributes from subordinate patched group aliases when those aliases are also patch group aliases -- this eliminates the circular dependency chaining.

Added IOverflowListener interface and updated Sources to support overflow listeners.  Updated ChannelState to register as an overflow listener so that it can visually depict to the user when the channel enters/exits source overflow state.  Added new color pattern for OVERFLOW with yellow text on red.
2017-02-10 06:36:57 -05:00
Denny Sheirer
6bc92e8b94 Merge pull request #174 from RachelOlivero/gui_accessibility_enhancements
Add a Text Label to the Mute Image Button
2017-02-04 20:21:44 +00:00
Denny
767b302ed7 Adds additional unresolved address exception handler to metadata updater 2017-02-04 07:32:22 -05:00
Rachel Olivero
952d930b5b Adds a screen reader accessible label to the mute button. Label toggles between mute and unmute to match the action that will be taken when the button is next pressed. 2017-02-03 10:19:52 -05:00
Denny
26087c465f Adds additional unresolved address exception handler to metadata updater 2017-01-29 12:37:09 -05:00
Denny
74c15d530b Resolves #164 - USB time out while processing buffer transfers. Decreases periodicity of processing the LibUsb timeout handler from 9 milliseconds to 5 milliseconds to reduce chance that buffers are not being serviced in time. 2017-01-29 11:02:12 -05:00
95 changed files with 7356 additions and 5817 deletions

View File

@@ -7,6 +7,7 @@
<w>fleetsync</w> <w>fleetsync</w>
<w>icecast</w> <w>icecast</w>
<w>ident</w> <w>ident</w>
<w>overflowable</w>
<w>polyphase</w> <w>polyphase</w>
<w>remez</w> <w>remez</w>
<w>samplerate</w> <w>samplerate</w>
@@ -17,6 +18,7 @@
<w>talkgroup</w> <w>talkgroup</w>
<w>tgid</w> <w>tgid</w>
<w>ultravox</w> <w>ultravox</w>
<w>wacn</w>
<w>xtea</w> <w>xtea</w>
</words> </words>
</dictionary> </dictionary>

View File

@@ -27,39 +27,9 @@
<root url="jar://$PROJECT_DIR$/imports/commons-codec-1.9.jar!/" /> <root url="jar://$PROJECT_DIR$/imports/commons-codec-1.9.jar!/" />
<root url="jar://$PROJECT_DIR$/imports/commons-logging-1.2.jar!/" /> <root url="jar://$PROJECT_DIR$/imports/commons-logging-1.2.jar!/" />
<root url="jar://$PROJECT_DIR$/imports/slf4j-api-1.7.21.jar!/" /> <root url="jar://$PROJECT_DIR$/imports/slf4j-api-1.7.21.jar!/" />
<root url="jar://$PROJECT_DIR$/imports/libusb4java-1.2.0-linux-aarch64.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC> <JAVADOC />
<root url="https://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/index.html" /> <SOURCES />
</JAVADOC>
<SOURCES>
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/examples" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/fluent-hc/src/examples" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/fluent-hc/src/main/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/fluent-hc/src/test/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient-cache/src/main/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient-cache/src/main/java-deprecated" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient-cache/src/test/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient-osgi/src/main/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient-osgi/src/test/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient-win/src/examples" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient-win/src/main/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient-win/src/test/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient/src/examples" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient/src/main/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient/src/main/java-deprecated" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient/src/test/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpmime/src/examples" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpmime/src/main/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpmime/src/main/java-deprecated" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpmime/src/test/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-asyncclient-4.1.2/httpasyncclient/src/examples" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-asyncclient-4.1.2/httpasyncclient/src/main/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-asyncclient-4.1.2/httpasyncclient/src/main/java-deprecated" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-asyncclient-4.1.2/httpasyncclient/src/test/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient/src/examples" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient/src/main/java" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient/src/main/java-deprecated" />
<root url="file://$USER_HOME$/Downloads/httpcomponents-client-4.5.2/httpclient/src/test/java" />
</SOURCES>
</library> </library>
</component> </component>

View File

@@ -1,10 +1,10 @@
0.3.0-beta1 20170129 0.3.0-beta1 20170129
- REQUIRES: Java 8 (or newer) for compatibility and eventual changeover to JavaFX
- FEATURE: audio streaming - adds capability to stream to multiple remote broadcast - FEATURE: audio streaming - adds capability to stream to multiple remote broadcast
servers (Broadcastify, Icecast v2.3 and v2.4+, and Shoutcast V1 and V2). Each servers (Broadcastify, Icecast v2.3 and v2.4+, and Shoutcast V1 and V2). Each
stream can be independently configured with a delay. Audio calls are directed stream can be independently configured with a delay. Audio calls are directed
to one or more streams by attaching one or more stream identifiers to each alias. to one or more streams by attaching one or more stream identifiers to each alias.
- Requires Java 8 (or newer) for compatibility and eventual changeover to JavaFX
- Extensive GUI updates for tuner, channel and alias management. Includes new - Extensive GUI updates for tuner, channel and alias management. Includes new
'Now Playing' channel view and 'Detail' view. 'Now Playing' channel view and 'Detail' view.
- Updated alias list management of alias id values and wildcards. Weighting is now - Updated alias list management of alias id values and wildcards. Weighting is now
@@ -17,7 +17,8 @@
- Implemented bounded queues for both tuner and individual channel IQ sample - Implemented bounded queues for both tuner and individual channel IQ sample
buffers. Bounded queues have ability to enter/exit overflow state when queue buffers. Bounded queues have ability to enter/exit overflow state when queue
size reaches overflow threshold and reset when queue size falls below the reset size reaches overflow threshold and reset when queue size falls below the reset
threshold. threshold. Channel state will show OVERFLOW in red/yellow.
- Improves handling of P25 TDMA channels (NO Phase 2 decoder support yet)
- Updated airspy controller for airspy-mini specific sample rate handling. - Updated airspy controller for airspy-mini specific sample rate handling.
- New developer remez filter designer tool and internal usage - New developer remez filter designer tool and internal usage

View File

@@ -7,7 +7,7 @@
<property name="major" value="0"/> <property name="major" value="0"/>
<property name="minor" value="3"/> <property name="minor" value="3"/>
<property name="patch" value="0"/> <property name="patch" value="0"/>
<property name="release" value="-beta2"/> <property name="release" value="-beta6"/>
<property name="filename" value="sdrtrunk_${major}.${minor}.${patch}${release}"/> <property name="filename" value="sdrtrunk_${major}.${minor}.${patch}${release}"/>
<!-- Build properties --> <!-- Build properties -->

Binary file not shown.

View File

@@ -185,27 +185,6 @@ public class Alias
*/ */
public void validate() public void validate()
{ {
//Check for duplicate broadcast channels
List<BroadcastChannel> broadcastChannels = getBroadcastChannels();
if(broadcastChannels.size() > 0)
{
Set<String> channelNames = new TreeSet<>();
for(BroadcastChannel broadcastChannel: broadcastChannels)
{
String channelName = broadcastChannel.getChannelName();
if(channelName == null || channelName.isEmpty() || channelNames.contains(channelName))
{
removeAliasID(broadcastChannel);
}
else
{
channelNames.add(channelName);
}
}
}
} }
/** /**
* Returns the priority level of this alias, if defined, or the default priority * Returns the priority level of this alias, if defined, or the default priority
@@ -336,9 +315,9 @@ public class Alias
* List of broadcast channels specified for this alias. * List of broadcast channels specified for this alias.
*/ */
@XmlTransient @XmlTransient
public List<BroadcastChannel> getBroadcastChannels() public Set<BroadcastChannel> getBroadcastChannels()
{ {
List<BroadcastChannel> broadcastChannels = new ArrayList<>(); Set<BroadcastChannel> broadcastChannels = new TreeSet<>();
for(AliasID id: getId()) for(AliasID id: getId())
{ {

View File

@@ -631,36 +631,47 @@ public class AliasList implements Listener<AliasEvent>
return mName; return mName;
} }
/**
* Indicates if this alias list has a non-null, non-empty name
*/
private boolean hasName()
{
return mName != null && !mName.isEmpty();
}
/** /**
* Receive alias change event notifications and modify this list accordingly * Receive alias change event notifications and modify this list accordingly
*/ */
@Override @Override
public void receive(AliasEvent event) public void receive(AliasEvent event)
{ {
Alias alias = event.getAlias(); if(hasName())
switch(event.getEvent())
{ {
case ADD: Alias alias = event.getAlias();
if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
{ switch(event.getEvent())
addAlias(alias); {
} case ADD:
break; if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
case CHANGE: {
if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList())) addAlias(alias);
{ }
addAlias(alias); break;
} case CHANGE:
break; if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
case DELETE: {
if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList())) addAlias(alias);
{ }
removeAlias(alias); break;
} case DELETE:
break; if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
default: {
break; removeAlias(alias);
}
break;
default:
break;
}
} }
} }
} }

View File

@@ -1,22 +1,28 @@
/******************************************************************************* /*******************************************************************************
* SDR Trunk * SDR Trunk
* Copyright (C) 2014-2016 Dennis Sheirer * Copyright (C) 2014-2016 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> * along with this program. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/ ******************************************************************************/
package alias; package alias;
import alias.AliasEvent.Event;
import alias.id.broadcast.BroadcastChannel;
import sample.Broadcaster;
import sample.Listener;
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@@ -24,195 +30,192 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import javax.swing.table.AbstractTableModel;
import alias.id.broadcast.BroadcastChannel;
import sample.Broadcaster;
import sample.Listener;
import alias.AliasEvent.Event;
/** /**
* Alias Model * Alias Model
*/ */
public class AliasModel extends AbstractTableModel public class AliasModel extends AbstractTableModel
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final int COLUMN_LIST = 0; public static final int COLUMN_LIST = 0;
public static final int COLUMN_GROUP = 1; public static final int COLUMN_GROUP = 1;
public static final int COLUMN_NAME = 2; public static final int COLUMN_NAME = 2;
public static final int COLUMN_ICON = 3; public static final int COLUMN_ICON = 3;
public static final int COLUMN_COLOR = 4; public static final int COLUMN_COLOR = 4;
private List<Alias> mAliases = new CopyOnWriteArrayList<>(); private List<Alias> mAliases = new CopyOnWriteArrayList<>();
private Broadcaster<AliasEvent> mAliasEventBroadcaster = new Broadcaster<>(); private Broadcaster<AliasEvent> mAliasEventBroadcaster = new Broadcaster<>();
private Map<String,AliasList> mAliasListMap = new HashMap<>(); private Map<String,AliasList> mAliasListMap = new HashMap<>();
public AliasModel() public AliasModel()
{ {
} }
/** /**
* Unmodifiable list of all aliases currently in the model * Unmodifiable list of all aliases currently in the model
*/ */
public List<Alias> getAliases() public List<Alias> getAliases()
{ {
return Collections.unmodifiableList( mAliases ); return Collections.unmodifiableList(mAliases);
} }
public Alias getAliasAtIndex( int row )
{
if( mAliases.size() >= row )
{
return mAliases.get( row );
}
return null;
}
public AliasList getAliasList( String name )
{
if( mAliasListMap.containsKey( name ) )
{
return mAliasListMap.get( name );
}
AliasList aliasList = new AliasList( name );
for( Alias alias: mAliases )
{
if( alias.getList().equalsIgnoreCase( name ) )
{
aliasList.addAlias( alias );
}
}
mAliasListMap.put( name, aliasList ); public Alias getAliasAtIndex(int row)
{
if(mAliases.size() >= row)
{
return mAliases.get(row);
}
//Register the new alias list to receive updates from this model return null;
addListener( aliasList ); }
return aliasList;
}
/**
* Returns a list of unique alias list names from across the alias set
*/
public List<String> getListNames()
{
List<String> listNames = new ArrayList<>();
for( Alias alias: mAliases )
{
if( alias.hasList() && !listNames.contains( alias.getList() ) )
{
listNames.add( alias.getList() );
}
}
Collections.sort( listNames );
return listNames;
}
/**
* Returns a list of alias group names for all aliases
*/
public List<String> getGroupNames()
{
List<String> groupNames = new ArrayList<>();
for( Alias alias: mAliases ) public AliasList getAliasList(String name)
{ {
if( alias.hasGroup() && !groupNames.contains( alias.getGroup() ) ) if(name != null && mAliasListMap.containsKey(name))
{ {
groupNames.add( alias.getGroup() ); return mAliasListMap.get(name);
} }
}
Collections.sort( groupNames ); AliasList aliasList = new AliasList(name);
return groupNames;
}
/** if(name != null)
* Returns a list of alias group names for all aliases that have a matching {
* list name value for(Alias alias : mAliases)
*/ {
public List<String> getGroupNames( String listName ) if(alias.hasList() && alias.getList().equalsIgnoreCase(name))
{ {
List<String> groupNames = new ArrayList<>(); aliasList.addAlias(alias);
}
}
if( listName != null ) mAliasListMap.put(name, aliasList);
{
for( Alias alias: mAliases )
{
if( alias.hasList() &&
alias.hasGroup() &&
listName.equals( alias.getList() ) &&
!groupNames.contains( alias.getGroup() ) )
{
groupNames.add( alias.getGroup() );
}
}
}
Collections.sort( groupNames ); //Register the new alias list to receive updates from this model
addListener(aliasList);
return groupNames; }
}
/** return aliasList;
* Bulk loading of aliases }
*/
public void addAliases( List<Alias> aliases )
{
for( Alias alias: aliases )
{
addAlias( alias );
}
}
/** /**
* Adds the alias to the model * Returns a list of unique alias list names from across the alias set
*/ */
public int addAlias( Alias alias ) public List<String> getListNames()
{ {
if( alias != null ) List<String> listNames = new ArrayList<>();
{
mAliases.add( alias );
int index = mAliases.size() - 1; for(Alias alias : mAliases)
{
if(alias.hasList() && !listNames.contains(alias.getList()))
{
listNames.add(alias.getList());
}
}
fireTableRowsInserted( index, index ); Collections.sort(listNames);
broadcast( new AliasEvent( alias, Event.ADD ) );
return index; return listNames;
} }
return -1; /**
} * Returns a list of alias group names for all aliases
*/
/** public List<String> getGroupNames()
* Removes the channel from the model and broadcasts a channel remove event {
*/ List<String> groupNames = new ArrayList<>();
public void removeAlias( Alias alias )
{ for(Alias alias : mAliases)
if( alias != null ) {
{ if(alias.hasGroup() && !groupNames.contains(alias.getGroup()))
int index = mAliases.indexOf( alias ); {
groupNames.add(alias.getGroup());
mAliases.remove( alias ); }
}
fireTableRowsDeleted( index, index );
Collections.sort(groupNames);
broadcast( new AliasEvent( alias, Event.DELETE ) );
} return groupNames;
} }
/**
* Returns a list of alias group names for all aliases that have a matching
* list name value
*/
public List<String> getGroupNames(String listName)
{
List<String> groupNames = new ArrayList<>();
if(listName != null)
{
for(Alias alias : mAliases)
{
if(alias.hasList() &&
alias.hasGroup() &&
listName.equals(alias.getList()) &&
!groupNames.contains(alias.getGroup()))
{
groupNames.add(alias.getGroup());
}
}
}
Collections.sort(groupNames);
return groupNames;
}
/**
* Bulk loading of aliases
*/
public void addAliases(List<Alias> aliases)
{
for(Alias alias : aliases)
{
addAlias(alias);
}
}
/**
* Adds the alias to the model
*/
public int addAlias(Alias alias)
{
if(alias != null)
{
mAliases.add(alias);
int index = mAliases.size() - 1;
fireTableRowsInserted(index, index);
broadcast(new AliasEvent(alias, Event.ADD));
return index;
}
return -1;
}
/**
* Removes the channel from the model and broadcasts a channel remove event
*/
public void removeAlias(Alias alias)
{
if(alias != null)
{
int index = mAliases.indexOf(alias);
mAliases.remove(alias);
fireTableRowsDeleted(index, index);
broadcast(new AliasEvent(alias, Event.DELETE));
}
}
/** /**
* Renames any broadcast channels that have the previous name. * Renames any broadcast channels that have the previous name.
*
* @param previousName to rename * @param previousName to rename
* @param newName to assign to the broadcast channel * @param newName to assign to the broadcast channel
*/ */
@@ -223,11 +226,11 @@ public class AliasModel extends AbstractTableModel
return; return;
} }
for(Alias alias: mAliases) for(Alias alias : mAliases)
{ {
if(alias.hasBroadcastChannel(previousName)) if(alias.hasBroadcastChannel(previousName))
{ {
for(BroadcastChannel broadcastChannel: alias.getBroadcastChannels()) for(BroadcastChannel broadcastChannel : alias.getBroadcastChannels())
{ {
if(broadcastChannel.getChannelName().contentEquals(previousName)) if(broadcastChannel.getChannelName().contentEquals(previousName))
{ {
@@ -238,85 +241,85 @@ public class AliasModel extends AbstractTableModel
} }
} }
@Override @Override
public int getRowCount() public int getRowCount()
{ {
return mAliases.size(); return mAliases.size();
} }
@Override @Override
public int getColumnCount() public int getColumnCount()
{ {
return 5; return 5;
} }
@Override @Override
public String getColumnName( int columnIndex ) public String getColumnName(int columnIndex)
{ {
switch( columnIndex ) switch(columnIndex)
{ {
case COLUMN_LIST: case COLUMN_LIST:
return "List"; return "List";
case COLUMN_GROUP: case COLUMN_GROUP:
return "Group"; return "Group";
case COLUMN_NAME: case COLUMN_NAME:
return "Name"; return "Name";
case COLUMN_ICON: case COLUMN_ICON:
return "Icon"; return "Icon";
case COLUMN_COLOR: case COLUMN_COLOR:
return "Color"; return "Color";
} }
return null;
}
@Override return null;
public Class<?> getColumnClass( int columnIndex ) }
{
if( columnIndex == COLUMN_COLOR )
{
return Integer.class;
}
return String.class;
}
@Override @Override
public boolean isCellEditable( int rowIndex, int columnIndex ) public Class<?> getColumnClass(int columnIndex)
{ {
return false; if(columnIndex == COLUMN_COLOR)
} {
return Integer.class;
}
@Override return String.class;
public Object getValueAt( int rowIndex, int columnIndex ) }
{
Alias alias = mAliases.get( rowIndex );
switch( columnIndex )
{
case COLUMN_LIST:
return alias.getList();
case COLUMN_GROUP:
return alias.getGroup();
case COLUMN_NAME:
return alias.getName();
case COLUMN_ICON:
return alias.getIconName();
case COLUMN_COLOR:
return alias.getColor();
}
return null;
}
@Override @Override
public void setValueAt( Object aValue, int rowIndex, int columnIndex ) public boolean isCellEditable(int rowIndex, int columnIndex)
{ {
throw new IllegalArgumentException( "Not yet implemented" ); return false;
} }
public void broadcast( AliasEvent event ) @Override
{ public Object getValueAt(int rowIndex, int columnIndex)
{
Alias alias = mAliases.get(rowIndex);
switch(columnIndex)
{
case COLUMN_LIST:
return alias.getList();
case COLUMN_GROUP:
return alias.getGroup();
case COLUMN_NAME:
return alias.getName();
case COLUMN_ICON:
return alias.getIconName();
case COLUMN_COLOR:
return alias.getColor();
}
return null;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex)
{
throw new IllegalArgumentException("Not yet implemented");
}
public void broadcast(AliasEvent event)
{
Alias alias = event.getAlias(); Alias alias = event.getAlias();
//Validate the alias following a user action that changed the alias or any alias IDs //Validate the alias following a user action that changed the alias or any alias IDs
@@ -325,23 +328,23 @@ public class AliasModel extends AbstractTableModel
alias.validate(); alias.validate();
} }
if( event.getEvent() == Event.CHANGE ) if(event.getEvent() == Event.CHANGE)
{ {
int index = mAliases.indexOf( event.getAlias() ); int index = mAliases.indexOf(event.getAlias());
fireTableRowsUpdated( index, index ); fireTableRowsUpdated(index, index);
} }
mAliasEventBroadcaster.broadcast( event ); mAliasEventBroadcaster.broadcast(event);
} }
public void addListener( Listener<AliasEvent> listener ) public void addListener(Listener<AliasEvent> listener)
{ {
mAliasEventBroadcaster.addListener( listener ); mAliasEventBroadcaster.addListener(listener);
} }
public void removeListener( Listener<AliasEvent> listener ) public void removeListener(Listener<AliasEvent> listener)
{ {
mAliasEventBroadcaster.removeListener( listener ); mAliasEventBroadcaster.removeListener(listener);
} }
} }

View File

@@ -24,12 +24,20 @@ import alias.id.AliasIDType;
import alias.id.broadcast.BroadcastChannel; import alias.id.broadcast.BroadcastChannel;
import alias.id.priority.Priority; import alias.id.priority.Priority;
import alias.id.talkgroup.TalkgroupID; import alias.id.talkgroup.TalkgroupID;
import gui.SDRTrunk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import playlist.version1.System;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.TreeSet;
public class PatchGroupAlias extends Alias public class PatchGroupAlias extends Alias
{ {
private final static Logger mLog = LoggerFactory.getLogger(PatchGroupAlias.class);
private Alias mPatchGroupAlias; private Alias mPatchGroupAlias;
private List<Alias> mPatchedAliases = new ArrayList<>(); private List<Alias> mPatchedAliases = new ArrayList<>();
private List<String> mPatchedTalkgroupIDs = new ArrayList<>(); private List<String> mPatchedTalkgroupIDs = new ArrayList<>();
@@ -168,11 +176,14 @@ public class PatchGroupAlias extends Alias
for(Alias alias: mPatchedAliases) for(Alias alias: mPatchedAliases)
{ {
for(AliasAction action: alias.getAction()) if(!(alias instanceof PatchGroupAlias))
{ {
if(!aliasActions.contains(action)) for(AliasAction action: alias.getAction())
{ {
aliasActions.add(action); if(!aliasActions.contains(action))
{
aliasActions.add(action);
}
} }
} }
} }
@@ -185,7 +196,7 @@ public class PatchGroupAlias extends Alias
{ {
for(Alias alias: mPatchedAliases) for(Alias alias: mPatchedAliases)
{ {
if(alias.hasActions()) if(!(alias instanceof PatchGroupAlias) && alias.hasActions())
{ {
return true; return true;
} }
@@ -194,20 +205,44 @@ public class PatchGroupAlias extends Alias
return hasPatchGroupAlias() && getPatchGroupAlias().hasActions(); return hasPatchGroupAlias() && getPatchGroupAlias().hasActions();
} }
/**
* Returns the highest listenable audio priority defined among the aliases in the group, or returns 'Do Not Monitor'
* if that is the only priority defined. Otherwise, returns default (100) priority.
*/
@Override @Override
public int getCallPriority() public int getCallPriority()
{ {
int highestPriority = (hasPatchGroupAlias() ? getPatchGroupAlias().getCallPriority() : Priority.DEFAULT_PRIORITY); boolean hasDoNotMonitor = false;
int highestPriority = (hasPatchGroupAlias() ? getPatchGroupAlias().getCallPriority() : Priority.DEFAULT_PRIORITY + 1);
for(Alias alias: mPatchedAliases) for(Alias alias: mPatchedAliases)
{ {
if(alias.hasCallPriority() && alias.getCallPriority() < highestPriority) if(!(alias instanceof PatchGroupAlias) && alias.hasCallPriority() && alias.getCallPriority() < highestPriority)
{ {
highestPriority = alias.getCallPriority(); if(alias.getCallPriority() == Priority.DO_NOT_MONITOR)
{
hasDoNotMonitor = true;
}
else
{
highestPriority = alias.getCallPriority();
}
} }
} }
return highestPriority; if(highestPriority <= Priority.DEFAULT_PRIORITY)
{
return highestPriority;
}
else if(hasDoNotMonitor)
{
return Priority.DO_NOT_MONITOR;
}
else
{
return Priority.DEFAULT_PRIORITY;
}
} }
@Override @Override
@@ -220,7 +255,7 @@ public class PatchGroupAlias extends Alias
for(Alias alias: mPatchedAliases) for(Alias alias: mPatchedAliases)
{ {
if(alias.hasCallPriority()) if(!(alias instanceof PatchGroupAlias) && alias.hasCallPriority())
{ {
return true; return true;
} }
@@ -239,7 +274,7 @@ public class PatchGroupAlias extends Alias
for(Alias alias: mPatchedAliases) for(Alias alias: mPatchedAliases)
{ {
if(alias.isRecordable()) if(!(alias instanceof PatchGroupAlias) && alias.isRecordable())
{ {
return true; return true;
} }
@@ -258,7 +293,7 @@ public class PatchGroupAlias extends Alias
for(Alias alias: mPatchedAliases) for(Alias alias: mPatchedAliases)
{ {
if(alias.isStreamable()) if(!(alias instanceof PatchGroupAlias) && alias.isStreamable())
{ {
return true; return true;
} }
@@ -268,9 +303,9 @@ public class PatchGroupAlias extends Alias
} }
@Override @Override
public List<BroadcastChannel> getBroadcastChannels() public Set<BroadcastChannel> getBroadcastChannels()
{ {
List<BroadcastChannel> broadcastChannels = new ArrayList<>(); Set<BroadcastChannel> broadcastChannels = new TreeSet<>();
if(hasPatchGroupAlias()) if(hasPatchGroupAlias())
{ {
@@ -279,12 +314,9 @@ public class PatchGroupAlias extends Alias
for(Alias alias: mPatchedAliases) for(Alias alias: mPatchedAliases)
{ {
for(BroadcastChannel broadcastChannel: alias.getBroadcastChannels()) if(!(alias instanceof PatchGroupAlias))
{ {
if(!broadcastChannels.contains(broadcastChannel)) broadcastChannels.addAll(alias.getBroadcastChannels());
{
broadcastChannels.add(broadcastChannel);
}
} }
} }
@@ -301,7 +333,7 @@ public class PatchGroupAlias extends Alias
for(Alias alias: mPatchedAliases) for(Alias alias: mPatchedAliases)
{ {
if(alias.hasBroadcastChannel(channel)) if(!(alias instanceof PatchGroupAlias) && alias.hasBroadcastChannel(channel))
{ {
return true; return true;
} }
@@ -309,4 +341,41 @@ public class PatchGroupAlias extends Alias
return false; return false;
} }
public static void main(String[] args)
{
Alias a1 = new Alias("Alias 1");
a1.addAliasID(new BroadcastChannel("Channel 1"));
a1.addAliasID(new BroadcastChannel("Channel 2"));
a1.addAliasID(new BroadcastChannel("Channel 3"));
a1.addAliasID(new BroadcastChannel("Channel 4"));
Alias a2 = new Alias("Alias 1");
a1.addAliasID(new BroadcastChannel("Channel 1"));
a1.addAliasID(new BroadcastChannel("Channel 2"));
a1.addAliasID(new BroadcastChannel("Channel 3"));
a1.addAliasID(new BroadcastChannel("Channel 4"));
Alias a3 = new Alias("Alias 1");
a1.addAliasID(new BroadcastChannel("Channel 1"));
a1.addAliasID(new BroadcastChannel("Channel 2"));
a1.addAliasID(new BroadcastChannel("Channel 3"));
a1.addAliasID(new BroadcastChannel("Channel 4"));
Alias a4 = new Alias("Alias 1");
a1.addAliasID(new BroadcastChannel("Channel 1"));
a1.addAliasID(new BroadcastChannel("Channel 2"));
a1.addAliasID(new BroadcastChannel("Channel 3"));
a1.addAliasID(new BroadcastChannel("Channel 4"));
PatchGroupAlias pga = new PatchGroupAlias();
pga.setPatchGroupAlias(a1);
pga.addPatchedAlias(a2);
pga.addPatchedAlias(a3);
pga.addPatchedAlias(a4);
Set<BroadcastChannel> bc = pga.getBroadcastChannels();
mLog.debug("Channels:" + bc);
}
} }

View File

@@ -25,76 +25,99 @@ import javax.xml.bind.annotation.XmlAttribute;
public class BroadcastChannel extends AliasID implements Comparable<BroadcastChannel> public class BroadcastChannel extends AliasID implements Comparable<BroadcastChannel>
{ {
private String mChannelName; private String mChannelName;
public BroadcastChannel() public BroadcastChannel()
{ {
//JAXB Constructor //JAXB Constructor
} }
@Override @Override
public int compareTo(BroadcastChannel other) public int compareTo(BroadcastChannel other)
{ {
if(mChannelName != null && other.getChannelName() != null) if(mChannelName != null && other.getChannelName() != null)
{ {
return mChannelName.compareTo(other.getChannelName()); return mChannelName.compareTo(other.getChannelName());
} }
else if(mChannelName != null) else if(mChannelName != null)
{ {
return -1; return -1;
} }
else else
{ {
return 1; return 1;
} }
} }
/** @Override
* Creates a named broadcast channel public boolean equals(Object o)
*/ {
public BroadcastChannel(String channelName) if(this == o)
{ {
mChannelName = channelName; return true;
} }
if(!(o instanceof BroadcastChannel))
{
return false;
}
/** BroadcastChannel that = (BroadcastChannel)o;
* Name of the broadcastAudio channel configuration
*/
@XmlAttribute(name="channel")
public String getChannelName()
{
return mChannelName;
}
/** return getChannelName() != null ? getChannelName().equals(that.getChannelName()) : that.getChannelName() == null;
* Sets the name of the broadcastAudio channel configuration }
*/
public void setChannelName(String channel)
{
mChannelName = channel;
}
@Override @Override
public AliasIDType getType() public int hashCode()
{ {
return AliasIDType.BROADCAST_CHANNEL; return getChannelName() != null ? getChannelName().hashCode() : 0;
} }
@Override /**
public boolean isValid() * Creates a named broadcast channel
{ */
return mChannelName != null; public BroadcastChannel(String channelName)
} {
mChannelName = channelName;
}
@Override /**
public boolean matches( AliasID id ) * Name of the broadcastAudio channel configuration
{ */
return false; @XmlAttribute(name = "channel")
} public String getChannelName()
{
@Override return mChannelName;
public String toString() }
{
/**
* Sets the name of the broadcastAudio channel configuration
*/
public void setChannelName(String channel)
{
mChannelName = channel;
}
@Override
public AliasIDType getType()
{
return AliasIDType.BROADCAST_CHANNEL;
}
@Override
public boolean isValid()
{
return mChannelName != null;
}
@Override
public boolean matches(AliasID id)
{
return false;
}
@Override
public String toString()
{
if(isValid()) if(isValid())
{ {
return "Broadcast Channel: " + mChannelName; return "Broadcast Channel: " + mChannelName;
@@ -103,5 +126,5 @@ public class BroadcastChannel extends AliasID implements Comparable<BroadcastCha
{ {
return "Broadcast Channel: None Selected"; return "Broadcast Channel: None Selected";
} }
} }
} }

View File

@@ -383,6 +383,7 @@ public class AudioPanel extends JPanel implements Listener<AudioEvent>
{ {
setIcon(UNMUTED_ICON); setIcon(UNMUTED_ICON);
setBorderPainted(false); setBorderPainted(false);
getAccessibleContext().setAccessibleName("Mute");
addActionListener(new ActionListener() addActionListener(new ActionListener()
{ {
@@ -402,6 +403,7 @@ public class AudioPanel extends JPanel implements Listener<AudioEvent>
public void run() public void run()
{ {
setIcon(mMuted ? MUTED_ICON : UNMUTED_ICON); setIcon(mMuted ? MUTED_ICON : UNMUTED_ICON);
getAccessibleContext().setAccessibleName(mMuted ? "Unmute" : "Mute");
} }
}); });
} }

View File

@@ -145,6 +145,10 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
session.write(updateRequest); session.write(updateRequest);
} }
} }
catch(UnresolvedAddressException uae)
{
//Do nothing - the server is temporarily unavailable
}
catch(Exception e) catch(Exception e)
{ {
Throwable throwableCause = e.getCause(); Throwable throwableCause = e.getCause();

View File

@@ -156,6 +156,8 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
disconnect(); disconnect();
} }
mConnecting.set(false);
} }
}; };
@@ -176,8 +178,6 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
{ {
mStreamingSession.closeNow(); mStreamingSession.closeNow();
} }
mConnecting.set(false);
} }
/** /**
@@ -256,6 +256,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
mSocketConnector = null; mSocketConnector = null;
mConnecting.set(false); mConnecting.set(false);
super.sessionClosed(session); super.sessionClosed(session);
} }

View File

@@ -25,6 +25,7 @@ import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSession;
import org.apache.mina.core.write.WriteTimeoutException;
import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector; import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -146,6 +147,8 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
disconnect(); disconnect();
} }
mConnecting.set(false);
} }
}; };
@@ -248,7 +251,13 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
{ {
String reason = ioe.getMessage(); String reason = ioe.getMessage();
if(reason.startsWith("Connection reset")) if(connected())
{
mLog.info("Streaming connection error detected - resetting connection - " + reason);
disconnect();
connect();
}
else if(reason.startsWith("Connection reset"))
{ {
mLog.info("Streaming connection reset by remote server - reestablishing connection"); mLog.info("Streaming connection reset by remote server - reestablishing connection");
disconnect(); disconnect();
@@ -264,14 +273,20 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
{ {
setBroadcastState(BroadcastState.ERROR); setBroadcastState(BroadcastState.ERROR);
disconnect(); disconnect();
mLog.error("Unrecognized IO error: " + reason + ". Streaming halted."); mLog.error("Unrecognized IO error: " + reason + ". Streaming halted.", cause);
} }
} }
else if(ioe instanceof WriteTimeoutException)
{
mLog.info("Network write timeout error - resetting connection");
disconnect();
connect();
}
else else
{ {
setBroadcastState(BroadcastState.ERROR); setBroadcastState(BroadcastState.ERROR);
disconnect(); disconnect();
mLog.error("Unspecified IO error - streaming halted."); mLog.error("Unspecified IO error - streaming halted.", cause);
} }
} }
else else
@@ -280,8 +295,6 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
setBroadcastState(BroadcastState.ERROR); setBroadcastState(BroadcastState.ERROR);
disconnect(); disconnect();
} }
mConnecting.set(false);
} }
@Override @Override

View File

@@ -168,6 +168,8 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
disconnect(); disconnect();
} }
mConnecting.set(false);
} }
}; };

View File

@@ -50,6 +50,7 @@ import properties.SystemProperties;
import util.ThreadPool; import util.ThreadPool;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException; import java.net.ConnectException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.ArrayList; import java.util.ArrayList;
@@ -203,6 +204,8 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
disconnect(); disconnect();
} }
mConnecting.set(false);
} }
}; };
@@ -244,43 +247,50 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?><metadata>"); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?><metadata>");
sb.append(UltravoxMetadata.ALBUM_TITLE.asXML(getConfiguration().getName())); try
sb.append(UltravoxMetadata.BROADCAST_CLIENT_APPLICATION.asXML(SystemProperties.getInstance().getApplicationName()));
if(getConfiguration().hasGenre())
{ {
sb.append(UltravoxMetadata.GENRE.asXML(getConfiguration().getGenre())); sb.append(UltravoxMetadata.ALBUM_TITLE.asXML(getConfiguration().getName()));
}
if(getConfiguration().hasURL()) sb.append(UltravoxMetadata.BROADCAST_CLIENT_APPLICATION.asXML(SystemProperties.getInstance().getApplicationName()));
{
sb.append(UltravoxMetadata.URL.asXML(getConfiguration().getURL()));
}
if(metadata != null) if(getConfiguration().hasGenre())
{
if(metadata.getPrimaryAddressTo().hasAlias())
{ {
sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getAlias().getName())); sb.append(UltravoxMetadata.GENRE.asXML(getConfiguration().getGenre()));
}
else if(metadata.getPrimaryAddressTo().hasIdentifier())
{
sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getIdentifier()));
} }
if(metadata.getPrimaryAddressFrom().hasAlias()) if(getConfiguration().hasURL())
{ {
sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getAlias().getName())); sb.append(UltravoxMetadata.URL.asXML(getConfiguration().getURL()));
} }
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
if(metadata != null)
{ {
sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getIdentifier())); if(metadata.getPrimaryAddressTo().hasAlias())
{
sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getAlias().getName()));
}
else if(metadata.getPrimaryAddressTo().hasIdentifier())
{
sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getIdentifier()));
}
if(metadata.getPrimaryAddressFrom().hasAlias())
{
sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getAlias().getName()));
}
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
{
sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getIdentifier()));
}
}
else
{
sb.append(UltravoxMetadata.TITLE_2.asXML("Scanning ..."));
} }
} }
else catch(UnsupportedEncodingException uee)
{ {
sb.append(UltravoxMetadata.TITLE_2.asXML("Scanning ...")); mLog.error("UTF-8 Encoding is not supported - shoutcast/ultravox metadata will not be updated");
} }
sb.append("</metadata>"); sb.append("</metadata>");

View File

@@ -18,6 +18,9 @@
******************************************************************************/ ******************************************************************************/
package audio.broadcast.shoutcast.v2.ultravox; package audio.broadcast.shoutcast.v2.ultravox;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public enum UltravoxMetadata public enum UltravoxMetadata
{ {
ALBUM_TITLE("TALB"), ALBUM_TITLE("TALB"),
@@ -58,11 +61,11 @@ public enum UltravoxMetadata
* @param value to enclose in XML tags * @param value to enclose in XML tags
* @return xml tag wrapped value * @return xml tag wrapped value
*/ */
public String asXML(String value) public String asXML(String value) throws UnsupportedEncodingException
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("<").append(getXMLTag()).append(">"); sb.append("<").append(getXMLTag()).append(">");
sb.append(value); sb.append(new String(value.getBytes(), "UTF-8"));
sb.append("</").append(getXMLTag()).append(">"); sb.append("</").append(getXMLTag()).append(">");
return sb.toString(); return sb.toString();

View File

@@ -38,7 +38,7 @@ public class ChannelDetailPanel extends JPanel implements Listener<ProcessingCha
private JLabel mSystemLabel; private JLabel mSystemLabel;
private JLabel mSiteLabel; private JLabel mSiteLabel;
private JLabel mNameLabel; private JLabel mNameLabel;
private JTextArea mDetailTextArea; private JTextArea mDetailTextPane;
private ChannelProcessingManager mChannelProcessingManager; private ChannelProcessingManager mChannelProcessingManager;
private ProcessingChain mProcessingChain; private ProcessingChain mProcessingChain;
@@ -82,10 +82,10 @@ public class ChannelDetailPanel extends JPanel implements Listener<ProcessingCha
add(buttonPanel, "wrap"); add(buttonPanel, "wrap");
mDetailTextArea = new JTextArea(EMPTY_DETAILS); mDetailTextPane = new JTextArea(EMPTY_DETAILS);
DefaultCaret caret = (DefaultCaret)mDetailTextArea.getCaret(); DefaultCaret caret = (DefaultCaret)mDetailTextPane.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
add(new JScrollPane(mDetailTextArea)); add(new JScrollPane(mDetailTextPane));
} }
@Override @Override
@@ -126,7 +126,7 @@ public class ChannelDetailPanel extends JPanel implements Listener<ProcessingCha
mSystemLabel.setText(system); mSystemLabel.setText(system);
mSiteLabel.setText(site); mSiteLabel.setText(site);
mNameLabel.setText(name); mNameLabel.setText(name);
mDetailTextArea.setText(details); mDetailTextPane.setText(details);
} }
}); });
} }

View File

@@ -19,8 +19,6 @@
package channel.metadata; package channel.metadata;
import alias.Alias; import alias.Alias;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.Listener; import sample.Listener;
import java.util.ArrayList; import java.util.ArrayList;
@@ -30,8 +28,6 @@ import java.util.Map;
public class AttributeMonitor<T> public class AttributeMonitor<T>
{ {
private final static Logger mLog = LoggerFactory.getLogger(AttributeMonitor.class);
private Attribute mAttribute; private Attribute mAttribute;
private Listener<AttributeChangeRequest> mListener; private Listener<AttributeChangeRequest> mListener;
private boolean mHeuristicsEnabled = true; private boolean mHeuristicsEnabled = true;
@@ -50,8 +46,8 @@ public class AttributeMonitor<T>
* an internal mapping of values to occurrence counts is updated and a change is emitted once a value that is * an internal mapping of values to occurrence counts is updated and a change is emitted once a value that is
* different from the current value, has a higher occurrence count than the current value. If heuristics are * different from the current value, has a higher occurrence count than the current value. If heuristics are
* disabled, then a change is emitted at each change in the value. * disabled, then a change is emitted at each change in the value.
* @param t
* *
* @param t type
* @return true if the value was changed after processing * @return true if the value was changed after processing
*/ */
public boolean process(T t) public boolean process(T t)
@@ -83,7 +79,7 @@ public class AttributeMonitor<T>
{ {
int count = mOccurrenceCounts.get(mCurrentValue); int count = mOccurrenceCounts.get(mCurrentValue);
for(Map.Entry<T,Integer> entry: mOccurrenceCounts.entrySet()) for(Map.Entry<T,Integer> entry : mOccurrenceCounts.entrySet())
{ {
if(entry.getValue() > count) if(entry.getValue() > count)
{ {
@@ -155,35 +151,4 @@ public class AttributeMonitor<T>
{ {
return mCurrentValue != null; return mCurrentValue != null;
} }
public static void main(String[] args)
{
AttributeMonitor<String> monitor = new AttributeMonitor<>(Attribute.PRIMARY_ADDRESS_TO, new Listener<AttributeChangeRequest>()
{
@Override
public void receive(AttributeChangeRequest attributeChangeRequest)
{
mLog.debug("Attribute Changed - value:" + attributeChangeRequest.getValue());
}
});
monitor.addIllegalValue("0000");
monitor.addIllegalValue("000000");
monitor.process("ABCD");
monitor.process("EFGH");
monitor.process("0000");
monitor.process("0000");
monitor.process("ABCD");
monitor.reset();
monitor.process("EFGH");
monitor.process("ABCD");
monitor.process("ABCD");
monitor.process("EFGH");
monitor.process("EFGH");
monitor.process("000000");
monitor.process("000000");
monitor.process("000000");
monitor.process("000000");
}
} }

View File

@@ -210,6 +210,10 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "idle", Color.WHITE); background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "idle", Color.WHITE);
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "idle", Color.BLUE); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "idle", Color.BLUE);
break; break;
case OVERFLOW:
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "overflow", Color.RED);
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "overflow", Color.YELLOW);
break;
case RESET: case RESET:
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "reset", Color.PINK); background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "reset", Color.PINK);
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "reset", Color.YELLOW); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "reset", Color.YELLOW);

View File

@@ -51,7 +51,7 @@ public class ChannelMetadataViewer extends JPanel
mChannelDetailPanel = new ChannelDetailPanel(channelProcessingManager); mChannelDetailPanel = new ChannelDetailPanel(channelProcessingManager);
mCallEventPanel = new CallEventPanel(iconManager); mCallEventPanel = new CallEventPanel(iconManager);
mMessageActivityPanel = new MessageActivityPanel(channelProcessingManager); mMessageActivityPanel = new MessageActivityPanel(channelProcessingManager);
mChannelSpectrumPanel = new ChannelSpectrumPanel(settingsManager, channelProcessingManager); // mChannelSpectrumPanel = new ChannelSpectrumPanel(settingsManager, channelProcessingManager);
mChannelMetadataPanel = new ChannelMetadataPanel(channelProcessingManager, iconManager); mChannelMetadataPanel = new ChannelMetadataPanel(channelProcessingManager, iconManager);
init(); init();

View File

@@ -28,6 +28,8 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.TreeSet;
public class Metadata public class Metadata
{ {
@@ -61,7 +63,7 @@ public class Metadata
private Integer mAudioPriority; private Integer mAudioPriority;
protected Boolean mRecordable = false; protected Boolean mRecordable = false;
protected Boolean mDoNotRecord; protected Boolean mDoNotRecord;
private List<BroadcastChannel> mBroadcastChannels; private Set<BroadcastChannel> mBroadcastChannels;
/** /**
@@ -166,7 +168,7 @@ public class Metadata
/** /**
* List of de-duplicated broadcast channels aggregated from the primary and secondary TO/FROM aliases. * List of de-duplicated broadcast channels aggregated from the primary and secondary TO/FROM aliases.
*/ */
public List<BroadcastChannel> getBroadcastChannels() public Set<BroadcastChannel> getBroadcastChannels()
{ {
if(mBroadcastChannels == null) if(mBroadcastChannels == null)
{ {
@@ -582,50 +584,26 @@ public class Metadata
*/ */
private void determineBroadcastChannels() private void determineBroadcastChannels()
{ {
mBroadcastChannels = new ArrayList<>(); mBroadcastChannels = new TreeSet<>();
if(mPrimaryAddressTo.hasAlias() && mPrimaryAddressTo.getAlias().isStreamable()) if(mPrimaryAddressTo.hasAlias() && mPrimaryAddressTo.getAlias().isStreamable())
{ {
for(BroadcastChannel broadcastChannel: mPrimaryAddressTo.getAlias().getBroadcastChannels()) mBroadcastChannels.addAll(mPrimaryAddressTo.getAlias().getBroadcastChannels());
{
if(!mBroadcastChannels.contains(broadcastChannel))
{
mBroadcastChannels.add(broadcastChannel);
}
}
} }
if(mPrimaryAddressFrom.hasAlias() && mPrimaryAddressFrom.getAlias().isStreamable()) if(mPrimaryAddressFrom.hasAlias() && mPrimaryAddressFrom.getAlias().isStreamable())
{ {
for(BroadcastChannel broadcastChannel: mPrimaryAddressFrom.getAlias().getBroadcastChannels()) mBroadcastChannels.addAll(mPrimaryAddressFrom.getAlias().getBroadcastChannels());
{
if(!mBroadcastChannels.contains(broadcastChannel))
{
mBroadcastChannels.add(broadcastChannel);
}
}
} }
if(mSecondaryAddressTo.hasAlias() && mSecondaryAddressTo.getAlias().isStreamable()) if(mSecondaryAddressTo.hasAlias() && mSecondaryAddressTo.getAlias().isStreamable())
{ {
for(BroadcastChannel broadcastChannel: mSecondaryAddressTo.getAlias().getBroadcastChannels()) mBroadcastChannels.addAll(mSecondaryAddressTo.getAlias().getBroadcastChannels());
{
if(!mBroadcastChannels.contains(broadcastChannel))
{
mBroadcastChannels.add(broadcastChannel);
}
}
} }
if(mSecondaryAddressFrom.hasAlias() && mSecondaryAddressFrom.getAlias().isStreamable()) if(mSecondaryAddressFrom.hasAlias() && mSecondaryAddressFrom.getAlias().isStreamable())
{ {
for(BroadcastChannel broadcastChannel: mSecondaryAddressFrom.getAlias().getBroadcastChannels()) mBroadcastChannels.addAll(mSecondaryAddressFrom.getAlias().getBroadcastChannels());
{
if(!mBroadcastChannels.contains(broadcastChannel))
{
mBroadcastChannels.add(broadcastChannel);
}
}
} }
} }

View File

@@ -35,6 +35,7 @@ import module.decode.event.ICallEventProvider;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sample.Listener; import sample.Listener;
import sample.real.IOverflowListener;
import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
@@ -42,7 +43,7 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class ChannelState extends Module implements ICallEventProvider, IDecoderStateEventListener, public class ChannelState extends Module implements ICallEventProvider, IDecoderStateEventListener,
IDecoderStateEventProvider, ISquelchStateProvider, IAttributeChangeRequestListener IDecoderStateEventProvider, ISquelchStateProvider, IAttributeChangeRequestListener, IOverflowListener
{ {
private final static Logger mLog = LoggerFactory.getLogger(ChannelState.class); private final static Logger mLog = LoggerFactory.getLogger(ChannelState.class);
@@ -63,6 +64,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
private boolean mSquelchLocked = false; private boolean mSquelchLocked = false;
private boolean mSelected = false; private boolean mSelected = false;
private boolean mSourceOverflow = false;
private long mStandardChannelFadeTimeout = FADE_TIMEOUT_DELAY; private long mStandardChannelFadeTimeout = FADE_TIMEOUT_DELAY;
private long mTrafficChannelFadeTimeout = DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS * 1000; private long mTrafficChannelFadeTimeout = DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS * 1000;
@@ -123,6 +125,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
mState = State.IDLE; mState = State.IDLE;
mMutableMetadata.receive(new AttributeChangeRequest<State>(Attribute.CHANNEL_STATE, mState)); mMutableMetadata.receive(new AttributeChangeRequest<State>(Attribute.CHANNEL_STATE, mState));
mSourceOverflow = false;
} }
@Override @Override
@@ -350,15 +353,26 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
break; break;
} }
mMutableMetadata.receive(new AttributeChangeRequest<State>(Attribute.CHANNEL_STATE, mState)); mMutableMetadata.receive(new AttributeChangeRequest<State>(Attribute.CHANNEL_STATE,
} mSourceOverflow ? State.OVERFLOW : mState));
else
{
// mLog.debug( "Can't change from [" + mState + "] to [" + state + "]" );
} }
} }
} }
/**
* This method is invoked if the source buffer provider goes into overflow state. Since this is an external state,
* we use the mSourceOverflow variable to override the internal state reported to external listeners.
* @param overflow true to indicate an overflow state
*/
@Override
public void sourceOverflow(boolean overflow)
{
mSourceOverflow = overflow;
mMutableMetadata.receive(new AttributeChangeRequest<State>(Attribute.CHANNEL_STATE,
mSourceOverflow ? State.OVERFLOW : mState));
}
/** /**
* Sets the state and processes related actions * Sets the state and processes related actions
*/ */

View File

@@ -23,6 +23,9 @@ public abstract class DecoderState extends Module implements ActivitySummaryProv
IAttributeChangeRequestProvider, ICallEventProvider, IDecoderStateEventListener, IAttributeChangeRequestProvider, ICallEventProvider, IDecoderStateEventListener,
IDecoderStateEventProvider, IMessageListener IDecoderStateEventProvider, IMessageListener
{ {
protected String DIVIDER1 = "======================================================\n";
protected String DIVIDER2 = "------------------------------------------------------\n";
/* This has to be a broadcaster in order for references to persist */ /* This has to be a broadcaster in order for references to persist */
private Broadcaster<CallEvent> mCallEventBroadcaster = new Broadcaster<>(); private Broadcaster<CallEvent> mCallEventBroadcaster = new Broadcaster<>();
private Broadcaster<AttributeChangeRequest> mAttributeChangeRequestBroadcaster = new Broadcaster<>(); private Broadcaster<AttributeChangeRequest> mAttributeChangeRequestBroadcaster = new Broadcaster<>();
@@ -51,6 +54,14 @@ public abstract class DecoderState extends Module implements ActivitySummaryProv
return mAliasList != null; return mAliasList != null;
} }
/**
* Provides subclass reference to the call event broadcaster
*/
protected Broadcaster<CallEvent> getCallEventBroadcaster()
{
return mCallEventBroadcaster;
}
/** /**
* Reset the decoder state to prepare for processing a different sample * Reset the decoder state to prepare for processing a different sample
* source * source

View File

@@ -1,17 +1,17 @@
/******************************************************************************* /*******************************************************************************
* SDR Trunk * SDR Trunk
* Copyright (C) 2014-2016 Dennis Sheirer * Copyright (C) 2014-2016 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> * along with this program. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/ ******************************************************************************/
@@ -23,98 +23,94 @@ import java.util.EnumSet;
* Details the set of states for a channel and the allowable transition states * Details the set of states for a channel and the allowable transition states
*/ */
public enum State public enum State
{ {
IDLE( "IDLE" ) IDLE("IDLE")
{
@Override
public boolean canChangeTo( State state )
{ {
return state != TEARDOWN && @Override
state != RESET; public boolean canChangeTo(State state)
} {
}, return state != TEARDOWN && state != RESET && state != OVERFLOW;
CALL( "CALL" ) }
{ },
@Override CALL("CALL")
public boolean canChangeTo( State state )
{ {
return state == CONTROL || @Override
state == DATA || public boolean canChangeTo(State state)
state == ENCRYPTED || {
state == FADE || return state == CONTROL || state == DATA || state == ENCRYPTED || state == FADE || state == TEARDOWN;
state == TEARDOWN; }
} },
}, DATA("DATA")
DATA( "DATA" )
{
@Override
public boolean canChangeTo( State state )
{ {
return state == CALL || @Override
state == CONTROL || public boolean canChangeTo(State state)
state == ENCRYPTED || {
state == FADE || return state == CALL || state == CONTROL || state == ENCRYPTED || state == FADE || state == TEARDOWN;
state == TEARDOWN; }
} },
}, ENCRYPTED("ENCRYPTED")
ENCRYPTED( "ENCRYPTED" ) {
@Override
public boolean canChangeTo(State state)
{
return state == FADE || state == TEARDOWN;
}
},
CONTROL("CONTROL")
{
@Override
public boolean canChangeTo(State state)
{
return state == IDLE || state == FADE;
}
},
FADE("FADE")
{
@Override
public boolean canChangeTo(State state)
{
return state != FADE && state != RESET && state != OVERFLOW;
}
},
OVERFLOW("OVERFLOW")
{
@Override
public boolean canChangeTo(State state)
{
return false;
}
},
RESET("RESET")
{
@Override
public boolean canChangeTo(State state)
{
return state == IDLE;
}
},
TEARDOWN("TEARDOWN")
{
@Override
public boolean canChangeTo(State state)
{
return state == RESET;
}
};
private String mDisplayValue;
public static final EnumSet<State> CALL_STATES = EnumSet.of(CALL, CONTROL, DATA, ENCRYPTED);
public static final EnumSet<State> IDLE_STATES = EnumSet.of(IDLE, FADE);
private State(String displayValue)
{ {
@Override mDisplayValue = displayValue;
public boolean canChangeTo( State state ) }
{
return state == FADE || state == TEARDOWN; public abstract boolean canChangeTo(State state);
}
}, public String getDisplayValue()
CONTROL( "CONTROL" )
{ {
@Override return mDisplayValue;
public boolean canChangeTo( State state ) }
{
return state == IDLE ||
state == FADE;
}
},
FADE( "FADE" )
{
@Override
public boolean canChangeTo( State state )
{
return state != FADE &&
state != RESET;
}
},
RESET( "RESET" )
{
@Override
public boolean canChangeTo(State state)
{
return state == IDLE;
}
},
TEARDOWN( "TEARDOWN" )
{
@Override
public boolean canChangeTo(State state)
{
return state == RESET;
}
};
private String mDisplayValue;
public static final EnumSet<State> CALL_STATES = EnumSet.of( CALL, CONTROL, DATA, ENCRYPTED );
public static final EnumSet<State> IDLE_STATES = EnumSet.of( IDLE, FADE );
private State( String displayValue )
{
mDisplayValue = displayValue;
}
public abstract boolean canChangeTo( State state );
public String getDisplayValue()
{
return mDisplayValue;
}
} }

View File

@@ -84,8 +84,6 @@ public class TrafficChannelManager extends Module implements ICallEventProvider,
* @param system label to use to describe the system * @param system label to use to describe the system
* @param site label to use to describe the site * @param site label to use to describe the site
* @param aliasListName designated for the channel * @param aliasListName designated for the channel
* @param trafficChannelTimeout - millisecond call timer limit used when an
* end of call signalling event is not decoded.
* @param trafficChannelPoolSize - maximum number of allocated traffic channels * @param trafficChannelPoolSize - maximum number of allocated traffic channels
* in the pool * in the pool
*/ */
@@ -96,7 +94,6 @@ public class TrafficChannelManager extends Module implements ICallEventProvider,
String system, String system,
String site, String site,
String aliasListName, String aliasListName,
long trafficChannelTimeout,
int trafficChannelPoolSize) int trafficChannelPoolSize)
{ {
mChannelModel = channelModel; mChannelModel = channelModel;

View File

@@ -1,5 +1,9 @@
package controller; package controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.ThreadPool;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@@ -8,24 +12,23 @@ import java.util.concurrent.atomic.AtomicInteger;
*/ */
public class NamingThreadFactory implements ThreadFactory public class NamingThreadFactory implements ThreadFactory
{ {
static final AtomicInteger poolNumber = new AtomicInteger(1); private final static Logger mLog = LoggerFactory.getLogger(ThreadPool.class);
private static final AtomicInteger mPoolNumber = new AtomicInteger(1);
final ThreadGroup mThreadGroup; private final ThreadGroup mThreadGroup;
final AtomicInteger mThreadNumber = new AtomicInteger(1); private final AtomicInteger mThreadNumber = new AtomicInteger(1);
final String mNamePrefix; private final String mNamePrefix;
public NamingThreadFactory( String prefix ) public NamingThreadFactory( String prefix )
{ {
SecurityManager s = System.getSecurityManager(); SecurityManager s = System.getSecurityManager();
mThreadGroup = (s != null)? s.getThreadGroup() : mThreadGroup = (s != null)? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
Thread.currentThread().getThreadGroup();
mNamePrefix = prefix + " pool-" + mNamePrefix = prefix + " pool-" + mPoolNumber.getAndIncrement() + "-thread-";
poolNumber.getAndIncrement() +
"-thread-";
} }
public Thread newThread( Runnable runnable ) public Thread newThread( Runnable runnable )
@@ -42,7 +45,16 @@ public class NamingThreadFactory implements ThreadFactory
{ {
thread.setPriority( Thread.NORM_PRIORITY ); thread.setPriority( Thread.NORM_PRIORITY );
} }
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
@Override
public void uncaughtException(Thread t, Throwable e)
{
mLog.error("Error while executing runnable in scheduled thread pool [" + t.getName() + "]", e);
}
});
return thread; return thread;
} }
} }

View File

@@ -1,65 +1,64 @@
package dsp.filter.design; package dsp.filter.design;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dsp.filter.fir.FIRFilterSpecification; import dsp.filter.fir.FIRFilterSpecification;
import dsp.filter.fir.remez.RemezFIRFilterDesigner; import dsp.filter.fir.remez.RemezFIRFilterDesigner;
import javafx.application.Application; import javafx.application.Application;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FilterViewer extends Application public class FilterViewer extends Application
{ {
private final static Logger mLog = LoggerFactory.getLogger( FilterViewer.class ); private final static Logger mLog = LoggerFactory.getLogger(FilterViewer.class);
/** /**
* Developer tool to visualize filter designs * Developer tool to visualize filter designs
*/ */
public FilterViewer() public FilterViewer()
{ {
} }
@Override
public void start( Stage primaryStage ) throws Exception
{
Scene scene = new Scene( new FilterView( getFilter() ) );
primaryStage.setTitle( "Filter Viewer" );
primaryStage.setScene( scene );
primaryStage.show();
}
public static void main( String[] args )
{
launch( args );
}
/** @Override
* Provides the filter to visualize. Modify this method to visualize your filter design. public void start(Stage primaryStage) throws Exception
*/ {
private float[] getFilter() Scene scene = new Scene(new FilterView(getFilter()));
{
// FIRFilterSpecification specification = FIRFilterSpecification.lowPassBuilder() primaryStage.setTitle("Filter Viewer");
// .sampleRate( 48000 ) primaryStage.setScene(scene);
// .gridDensity( 16 ) primaryStage.show();
// .passBandCutoff( 3200 ) }
// .passBandAmplitude( 1.0 )
// .passBandRipple( 0.02 ) public static void main(String[] args)
// .stopBandStart( 4000 ) {
// .stopBandAmplitude( 0.0 ) launch(args);
// .stopBandRipple( 0.03 ) }
// .build();
/**
FIRFilterSpecification specification = FIRFilterSpecification.highPassBuilder() * Provides the filter to visualize. Modify this method to visualize your filter design.
.sampleRate( 24000 ) */
.stopBandCutoff( 800 ) private float[] getFilter()
.stopBandAmplitude( 0.0 ) {
.stopBandRipple( 0.03 ) FIRFilterSpecification specification = FIRFilterSpecification.lowPassBuilder()
.passBandStart( 1000 ) .sampleRate(48000)
.passBandAmplitude( 1.0 ) .gridDensity(16)
.passBandRipple( 0.08 ) .passBandCutoff(2500)
.build(); .passBandAmplitude(1.0)
.passBandRipple(0.01)
.stopBandStart(4000)
.stopBandAmplitude(0.0)
.stopBandRipple(0.008)
.build();
// FIRFilterSpecification specification = FIRFilterSpecification.highPassBuilder()
// .sampleRate(24000)
// .stopBandCutoff(800)
// .stopBandAmplitude(0.0)
// .stopBandRipple(0.03)
// .passBandStart(1000)
// .passBandAmplitude(1.0)
// .passBandRipple(0.08)
// .build();
// FIRFilterSpecification specification = FIRFilterSpecification.bandPassBuilder() // FIRFilterSpecification specification = FIRFilterSpecification.bandPassBuilder()
// .sampleRate( 48000 ) // .sampleRate( 48000 )
@@ -71,24 +70,25 @@ public class FilterViewer extends Application
// .passRipple( 0.008) // .passRipple( 0.008)
// .build(); // .build();
float[] taps = null; float[] taps = null;
// taps = FilterFactory.getLowPass( 16000, 2400, 73, WindowType.HANNING ); // taps = FilterFactory.getLowPass(48000, 6750, 7500, 60,
// Window.WindowType.HAMMING, true);
try try
{ {
RemezFIRFilterDesigner designer = new RemezFIRFilterDesigner( specification ); RemezFIRFilterDesigner designer = new RemezFIRFilterDesigner(specification);
if( designer.isValid() ) if(designer.isValid())
{ {
taps = designer.getImpulseResponse(); taps = designer.getImpulseResponse();
} }
} }
catch( FilterDesignException fde ) catch(FilterDesignException fde)
{ {
mLog.error( "Filter design error", fde ); mLog.error("Filter design error", fde);
} }
return taps; return taps;
} }
} }

View File

@@ -538,6 +538,9 @@ public class ProcessingChain implements IChannelEventListener
module.reset(); module.reset();
} }
//Setup the channel state to monitor source overflow conditions
mSource.setOverflowListener(mChannelState);
/* Register with the source to receive sample data. Setup a /* Register with the source to receive sample data. Setup a
* timer task to process the buffer queues 50 times a second * timer task to process the buffer queues 50 times a second
* (every 20 ms) */ * (every 20 ms) */
@@ -606,6 +609,7 @@ public class ProcessingChain implements IChannelEventListener
if(mSource != null) if(mSource != null)
{ {
mSource.stop(); mSource.stop();
mSource.setOverflowListener(null);
switch(mSource.getSampleType()) switch(mSource.getSampleType())
{ {

View File

@@ -103,35 +103,35 @@ public class DecoderFactory
//Low-pass filter with ~60 dB attenuation and 89 taps //Low-pass filter with ~60 dB attenuation and 89 taps
private static final FIRFilterSpecification MPT1327_FILTER_SPECIFICATION = FIRFilterSpecification.lowPassBuilder() private static final FIRFilterSpecification MPT1327_FILTER_SPECIFICATION = FIRFilterSpecification.lowPassBuilder()
.sampleRate( 48000 ) .sampleRate( 48000 ).gridDensity( 16 ).passBandCutoff( 3200 ).passBandAmplitude( 1.0 ).passBandRipple( 0.02 )
.gridDensity( 16 ) .stopBandStart( 4000 ).stopBandAmplitude( 0.0 ).stopBandRipple( 0.03 ).build();
.passBandCutoff( 3200 )
.passBandAmplitude( 1.0 ) private static final FIRFilterSpecification P25_C4FM_IQ_SPECIFICATION = FIRFilterSpecification.lowPassBuilder()
.passBandRipple( 0.02 ) .sampleRate(48000).gridDensity(16).passBandCutoff(6750).passBandAmplitude(1.0).passBandRipple(0.01)
.stopBandStart( 4000 ) .stopBandStart(7000).stopBandAmplitude(0.0).stopBandRipple(0.008).build();
.stopBandAmplitude( 0.0 )
.stopBandRipple( 0.03 ) private static final FIRFilterSpecification P25_C4FM_DEMOD_SPECIFICATION = FIRFilterSpecification.lowPassBuilder()
.build(); .sampleRate(48000).gridDensity(16).passBandCutoff(2500).passBandAmplitude(1.0).passBandRipple(0.01)
.stopBandStart(4000).stopBandAmplitude(0.0).stopBandRipple(0.008).build();
private static float[] MPT1327_LOWPASS_FILTER; private static float[] MPT1327_LOWPASS_FILTER;
private static float[] P25_C4FM_IQ_FILTER;
private static float[] P25_C4FM_DEMOD_FILTER;
static static
{ {
try try
{ {
MPT1327_LOWPASS_FILTER = FilterFactory.getTaps(MPT1327_FILTER_SPECIFICATION); MPT1327_LOWPASS_FILTER = FilterFactory.getTaps(MPT1327_FILTER_SPECIFICATION);
P25_C4FM_IQ_FILTER = FilterFactory.getTaps(P25_C4FM_IQ_SPECIFICATION);
P25_C4FM_DEMOD_FILTER = FilterFactory.getTaps(P25_C4FM_DEMOD_SPECIFICATION);
} }
catch(Exception e) catch(Exception e)
{ {
mLog.error("Couldn't design MPT1327 bandpass filter"); mLog.error("Couldn't design startup filter(s)");
} }
} }
public static final boolean NO_REMOVE_DC = false;
public static final boolean REMOVE_DC = true;
public static final int NO_FREQUENCY_CORRECTION = 0;
/** /**
* Returns a list of one primary decoder and any auxiliary decoders, as * Returns a list of one primary decoder and any auxiliary decoders, as
* specified in the configurations. * specified in the configurations.
@@ -222,15 +222,13 @@ public class DecoderFactory
if(channelType == ChannelType.STANDARD) if(channelType == ChannelType.STANDARD)
{ {
long timeout = mptConfig.getCallTimeout() * 1000; //convert to milliseconds
modules.add(new TrafficChannelManager(channelModel, channelProcessingManager, decodeConfig, modules.add(new TrafficChannelManager(channelModel, channelProcessingManager, decodeConfig,
channel.getRecordConfiguration(), channel.getSystem(), channel.getSite(), channel.getRecordConfiguration(), channel.getSystem(), channel.getSite(),
(aliasList != null ? aliasList.getName() : null), timeout, mptConfig.getTrafficChannelPoolSize())); (aliasList != null ? aliasList.getName() : null), mptConfig.getTrafficChannelPoolSize()));
} }
modules.add(new FMDemodulatorModule(iqPass, iqStop)); modules.add(new FMDemodulatorModule(iqPass, iqStop));
modules.add(new DemodulatedAudioFilterModule(MPT1327_LOWPASS_FILTER, 1.0f)); modules.add(new DemodulatedAudioFilterModule(P25_C4FM_DEMOD_FILTER, 1.0f));
modules.add(new AudioModule(metadata)); modules.add(new AudioModule(metadata));
break; break;
case PASSPORT: case PASSPORT:
@@ -249,7 +247,8 @@ public class DecoderFactory
switch(modulation) switch(modulation)
{ {
case C4FM: case C4FM:
modules.add(new FMDemodulatorModule(6750, 7500)); modules.add(new FMDemodulatorModule(P25_C4FM_IQ_FILTER));
modules.add(new DemodulatedAudioFilterModule(P25_C4FM_DEMOD_FILTER, 1.0f));
modules.add(new P25_C4FMDecoder(aliasList, decodeConfig.getAFCMaximumCorrection())); modules.add(new P25_C4FMDecoder(aliasList, decodeConfig.getAFCMaximumCorrection()));
modules.add(new P25DecoderState(aliasList, channelType, Modulation.C4FM, modules.add(new P25DecoderState(aliasList, channelType, Modulation.C4FM,
p25Config.getIgnoreDataCalls())); p25Config.getIgnoreDataCalls()));
@@ -264,12 +263,9 @@ public class DecoderFactory
if(channelType == ChannelType.STANDARD) if(channelType == ChannelType.STANDARD)
{ {
//Set call timeout to 3 seconds for P25 traffic channels
long timeout = 3000;
modules.add(new TrafficChannelManager(channelModel, channelProcessingManager, decodeConfig, modules.add(new TrafficChannelManager(channelModel, channelProcessingManager, decodeConfig,
channel.getRecordConfiguration(), channel.getSystem(), channel.getSite(), channel.getRecordConfiguration(), channel.getSystem(), channel.getSite(),
(aliasList != null ? aliasList.getName() : null), timeout, p25Config.getTrafficChannelPoolSize())); (aliasList != null ? aliasList.getName() : null), p25Config.getTrafficChannelPoolSize()));
} }
modules.add(new P25AudioModule(metadata)); modules.add(new P25AudioModule(metadata));

View File

@@ -389,9 +389,9 @@ public class MPT1327DecoderState extends DecoderState
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Activity Summary\n"); sb.append("Activity Summary - Decoder: MPT-1327\n");
sb.append("Decoder:\tMPT-1327\n"); sb.append(DIVIDER1);
sb.append("Site:\t"); sb.append("Site: ");
if(mSite != null) if(mSite != null)
{ {
@@ -403,9 +403,7 @@ public class MPT1327DecoderState extends DecoderState
if(siteAlias != null) if(siteAlias != null)
{ {
sb.append(" "); sb.append(" ").append(siteAlias.getName()).append("\n");
sb.append(siteAlias.getName());
sb.append("\n");
} }
} }
} }
@@ -414,13 +412,11 @@ public class MPT1327DecoderState extends DecoderState
sb.append("Unknown\n"); sb.append("Unknown\n");
} }
sb.append("\n\n"); sb.append(DIVIDER2).append("Talkgroups: ");
sb.append("Talkgroups\n\n");
if(mGroups.isEmpty()) if(mGroups.isEmpty())
{ {
sb.append(" None\n"); sb.append("None\n");
} }
else else
{ {
@@ -429,8 +425,7 @@ public class MPT1327DecoderState extends DecoderState
for(String talkgroup : talkgroups) for(String talkgroup : talkgroups)
{ {
sb.append(" "); sb.append("\n ").append(talkgroup);
sb.append(talkgroup);
if(hasAliasList()) if(hasAliasList())
{ {
@@ -450,7 +445,7 @@ public class MPT1327DecoderState extends DecoderState
for(String member : members) for(String member : members)
{ {
sb.append(" >"); sb.append(" >");
sb.append(member); sb.append(member);
if(hasAliasList()) if(hasAliasList())
@@ -466,27 +461,26 @@ public class MPT1327DecoderState extends DecoderState
sb.append("\n"); sb.append("\n");
} }
sb.append("\n");
} }
} }
sb.append("\n"); sb.append(DIVIDER2).append("All Idents: ");
sb.append("Individual Idents\n");
if(mIdents.isEmpty()) if(mIdents.isEmpty())
{ {
sb.append(" None\n"); sb.append("None\n");
} }
else else
{ {
sb.append("\n");
Iterator<String> it = mIdents.iterator(); Iterator<String> it = mIdents.iterator();
while(it.hasNext()) while(it.hasNext())
{ {
String ident = it.next(); String ident = it.next();
sb.append(" "); sb.append("");
sb.append(ident); sb.append(ident);
sb.append(" "); sb.append(" ");

View File

@@ -19,9 +19,7 @@ package module.decode.p25;
import alias.Alias; import alias.Alias;
import alias.AliasList; import alias.AliasList;
import alias.PatchGroupAlias;
import alias.id.AliasIDType; import alias.id.AliasIDType;
import alias.id.talkgroup.TalkgroupID;
import channel.metadata.AliasedStringAttributeMonitor; import channel.metadata.AliasedStringAttributeMonitor;
import channel.metadata.Attribute; import channel.metadata.Attribute;
import channel.metadata.AttributeChangeRequest; import channel.metadata.AttributeChangeRequest;
@@ -150,6 +148,7 @@ public class P25DecoderState extends DecoderState
private static final DecimalFormat mFrequencyFormatter = private static final DecimalFormat mFrequencyFormatter =
new DecimalFormat("0.000000"); new DecimalFormat("0.000000");
private module.decode.p25.message.tsbk.osp.control.NetworkStatusBroadcast mNetworkStatus; private module.decode.p25.message.tsbk.osp.control.NetworkStatusBroadcast mNetworkStatus;
private NetworkStatusBroadcastExtended mNetworkStatusExtended; private NetworkStatusBroadcastExtended mNetworkStatusExtended;
private ProtectionParameterBroadcast mProtectionParameterBroadcast; private ProtectionParameterBroadcast mProtectionParameterBroadcast;
@@ -163,7 +162,6 @@ public class P25DecoderState extends DecoderState
private Map<Integer,IdentifierUpdate> mBands = new HashMap<>(); private Map<Integer,IdentifierUpdate> mBands = new HashMap<>();
private Map<String,Long> mRegistrations = new HashMap<>(); private Map<String,Long> mRegistrations = new HashMap<>();
private Map<String,IAdjacentSite> mNeighborMap = new HashMap<>(); private Map<String,IAdjacentSite> mNeighborMap = new HashMap<>();
private Map<String,List<String>> mPatchGroupMap = new HashMap<>();
private String mLastCommandEventID; private String mLastCommandEventID;
private String mLastPageEventID; private String mLastPageEventID;
@@ -188,6 +186,7 @@ public class P25DecoderState extends DecoderState
private P25CallEvent mCurrentCallEvent; private P25CallEvent mCurrentCallEvent;
private List<String> mCallDetectTalkgroups = new ArrayList<>(); private List<String> mCallDetectTalkgroups = new ArrayList<>();
private Map<String,P25CallEvent> mChannelCallMap = new HashMap<>(); private Map<String,P25CallEvent> mChannelCallMap = new HashMap<>();
private PatchGroupManager mPatchGroupManager;
public P25DecoderState(AliasList aliasList, public P25DecoderState(AliasList aliasList,
ChannelType channelType, ChannelType channelType,
@@ -199,6 +198,7 @@ public class P25DecoderState extends DecoderState
mModulation = modulation; mModulation = modulation;
mIgnoreDataCalls = ignoreDataCalls; mIgnoreDataCalls = ignoreDataCalls;
mPatchGroupManager = new PatchGroupManager(aliasList, getCallEventBroadcaster());
mSiteAttributeMonitor = new AliasedStringAttributeMonitor(Attribute.NETWORK_ID_2, mSiteAttributeMonitor = new AliasedStringAttributeMonitor(Attribute.NETWORK_ID_2,
getAttributeChangeRequestListener(), getAliasList(), AliasIDType.SITE); getAttributeChangeRequestListener(), getAliasList(), AliasIDType.SITE);
mFromTalkgroupMonitor = new AliasedStringAttributeMonitor(Attribute.PRIMARY_ADDRESS_FROM, mFromTalkgroupMonitor = new AliasedStringAttributeMonitor(Attribute.PRIMARY_ADDRESS_FROM,
@@ -2719,6 +2719,9 @@ public class P25DecoderState extends DecoderState
switch(((MotorolaTSBKMessage)tsbk).getMotorolaOpcode()) switch(((MotorolaTSBKMessage)tsbk).getMotorolaOpcode())
{ {
case PATCH_GROUP_CHANNEL_GRANT: case PATCH_GROUP_CHANNEL_GRANT:
//Cleanup patch groups - auto-expire any patch groups before we allocate a channel
mPatchGroupManager.cleanupPatchGroups();
PatchGroupVoiceChannelGrant pgvcg = (PatchGroupVoiceChannelGrant)tsbk; PatchGroupVoiceChannelGrant pgvcg = (PatchGroupVoiceChannelGrant)tsbk;
channel = pgvcg.getChannel(); channel = pgvcg.getChannel();
@@ -2739,7 +2742,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder(CallEventType.PATCH_GROUP_CALL) P25CallEvent event = new P25CallEvent.Builder(CallEventType.PATCH_GROUP_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (pgvcg.isTDMAChannel() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(pgvcg.getDownlinkFrequency()) .frequency(pgvcg.getDownlinkFrequency())
.from(from) .from(from)
@@ -2750,10 +2753,15 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
broadcast(new TrafficChannelAllocationEvent(this, if(!pgvcg.isTDMAChannel())
mChannelCallMap.get(channel))); {
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
}
break; break;
case PATCH_GROUP_CHANNEL_GRANT_UPDATE: case PATCH_GROUP_CHANNEL_GRANT_UPDATE:
//Cleanup patch groups - auto-expire any patch groups before we allocate a channel
mPatchGroupManager.cleanupPatchGroups();
PatchGroupVoiceChannelGrantUpdate gvcgu = (PatchGroupVoiceChannelGrantUpdate)tsbk; PatchGroupVoiceChannelGrantUpdate gvcgu = (PatchGroupVoiceChannelGrantUpdate)tsbk;
channel = gvcgu.getChannel1(); channel = gvcgu.getChannel1();
@@ -2767,10 +2775,8 @@ public class P25DecoderState extends DecoderState
{ {
P25CallEvent event = new P25CallEvent.Builder(CallEventType.PATCH_GROUP_CALL) P25CallEvent event = new P25CallEvent.Builder(CallEventType.PATCH_GROUP_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (gvcgu.isTDMAChannel1() ? " TDMA" : ""))
.details((gvcgu.isEncrypted() ? "ENCRYPTED " : "") + .details((gvcgu.isEncrypted() ? "ENCRYPTED " : ""))
"PATCH UPDATE - GROUP 2:" + gvcgu.getPatchGroupAddress2() +
" DN:" + gvcgu.getDownlinkFrequency2())
.frequency(gvcgu.getDownlinkFrequency1()) .frequency(gvcgu.getDownlinkFrequency1())
.to(to) .to(to)
.build(); .build();
@@ -2779,40 +2785,45 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
broadcast(new TrafficChannelAllocationEvent(this, if(!gvcgu.isTDMAChannel1())
mChannelCallMap.get(channel))); {
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
}
String channel2 = gvcgu.getChannel2();
String to2 = gvcgu.getPatchGroupAddress2();
if(hasCallEvent(channel2, null, to2))
{
updateCallEvent(channel2, null, to2);
}
else
{
P25CallEvent event = new P25CallEvent.Builder(CallEventType.PATCH_GROUP_CALL)
.aliasList(getAliasList())
.channel(channel2 + (gvcgu.isTDMAChannel2() ? " TDMA" : ""))
.details((gvcgu.isEncrypted() ? "ENCRYPTED " : ""))
.frequency(gvcgu.getDownlinkFrequency2())
.to(to2)
.build();
registerCallEvent(event);
broadcast(event);
}
if(!gvcgu.isTDMAChannel2())
{
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel2)));
}
break; break;
case PATCH_GROUP_ADD: case PATCH_GROUP_ADD:
PatchGroupAdd pga = (PatchGroupAdd)tsbk; PatchGroupAdd pga = (PatchGroupAdd)tsbk;
mPatchGroupManager.updatePatchGroup(pga.getPatchGroupAddress(), pga.getPatchedTalkgroups());
if(addPatchGroup(pga.getPatchGroupAddress(), pga.getPatchedTalkgroups()))
{
StringBuilder sb = new StringBuilder();
sb.append("PATCH GROUP:").append(pga.getPatchGroupAddress());
sb.append(" ").append(pga.getPatchedTalkgroups());
broadcast(new P25CallEvent.Builder(CallEventType.PATCH_GROUP_ADD)
.aliasList(getAliasList())
.details(sb.toString())
.build());
}
break; break;
case PATCH_GROUP_DELETE: case PATCH_GROUP_DELETE:
PatchGroupDelete pgd = (PatchGroupDelete)tsbk; PatchGroupDelete pgd = (PatchGroupDelete)tsbk;
mPatchGroupManager.removePatchGroup(pgd.getPatchGroupAddress());
if(removePatchGroup(pgd.getPatchGroupAddress(), pgd.getPatchedTalkgroups()))
{
StringBuilder sbpgd = new StringBuilder();
sbpgd.append("PATCH GROUP:").append(pgd.getPatchGroupAddress());
sbpgd.append(" ").append(pgd.getPatchedTalkgroups());
broadcast(new P25CallEvent.Builder(CallEventType.PATCH_GROUP_DELETE)
.aliasList(getAliasList())
.details(sbpgd.toString())
.build());
}
break; break;
case CCH_PLANNED_SHUTDOWN: case CCH_PLANNED_SHUTDOWN:
if(!mControlChannelShutdownLogged) if(!mControlChannelShutdownLogged)
@@ -2827,174 +2838,14 @@ public class P25DecoderState extends DecoderState
} }
} }
/**
* Creates a new patch group or updates an existing patch group with the patched talkgroup entries.
*
* @param patchGroupID for the patch group
* @param talkgroupsToAdd to include in the patch group
* @return true if the patch group or the patch group map was updated
*/
private boolean addPatchGroup(String patchGroupID, List<String> talkgroupsToAdd)
{
boolean updated = false;
if(patchGroupID != null && !talkgroupsToAdd.isEmpty())
{
List<String> patchedTalkgroups = mPatchGroupMap.get(patchGroupID);
if(patchedTalkgroups == null)
{
patchedTalkgroups = new ArrayList<>();
}
for(String talkgroupToAdd : talkgroupsToAdd)
{
//Exclude the patch group ID if it is included in the patched talkgroup list so that we don't have
//an infinite loop situation
if(talkgroupToAdd.equals(patchGroupID))
{
continue;
}
if(!patchedTalkgroups.contains(talkgroupToAdd))
{
patchedTalkgroups.add(talkgroupToAdd);
updated = true;
}
}
if(updated)
{
mPatchGroupMap.put(patchGroupID, patchedTalkgroups);
updatePatchAlias(patchGroupID, patchedTalkgroups);
}
}
return updated;
}
/**
* Removes the patched talkgroups from the patch group and removes the patch group from the patch group map if
* there are no more patched talkgroups in the patch group.
*
* @param patchGroupID for the patch group
* @param talkgroupsToRemove to remove from the patch group
* @return true if the patch group or the patch group map was updated
*/
private boolean removePatchGroup(String patchGroupID, List<String> talkgroupsToRemove)
{
boolean updated = false;
if(patchGroupID != null && !talkgroupsToRemove.isEmpty())
{
List<String> patchedTalkgroups = mPatchGroupMap.get(patchGroupID);
if(patchedTalkgroups != null)
{
for(String talkgroupToRemove : talkgroupsToRemove)
{
if(patchedTalkgroups.contains(talkgroupToRemove))
{
patchedTalkgroups.remove(talkgroupToRemove);
updated = true;
}
}
if(patchedTalkgroups.isEmpty())
{
mPatchGroupMap.remove(patchGroupID);
removePatchGroupAlias(patchGroupID);
updated = true;
}
else
{
updatePatchAlias(patchGroupID, patchedTalkgroups);
}
}
}
return updated;
}
/**
* Adds/updates a patch group alias to the alias list containing aliases for each of the patched talkgroups. If the
* patch group alias already exists, any patched talkgroups will be removed from the existing patch group alias and
* replaced with the aliases corresponding to the patched talkgroup aliases.
*
* @param patchGroupID for the patch group
* @param patchedTalkgroups containing the talkgroup IDs for each of the patched talkgroups
*/
private void updatePatchAlias(String patchGroupID, List<String> patchedTalkgroups)
{
PatchGroupAlias patchGroupAlias = null;
//Check for an existing alias for the patch talkgroup - do not include wildcard aliases
Alias existingAlias = getAliasList().getTalkgroupAlias(patchGroupID, false);
if(existingAlias instanceof PatchGroupAlias)
{
patchGroupAlias = (PatchGroupAlias)existingAlias;
}
else
{
patchGroupAlias = new PatchGroupAlias();
patchGroupAlias.addAliasID(new TalkgroupID(patchGroupID));
if(existingAlias != null)
{
getAliasList().removeAlias(existingAlias);
patchGroupAlias.setPatchGroupAlias(existingAlias);
}
getAliasList().addAlias(patchGroupAlias);
}
if(patchGroupAlias != null)
{
patchGroupAlias.setPatchedTalkgroupIDs(patchedTalkgroups);
patchGroupAlias.clearPatchedAliases();
for(String patchedTalkgroup : patchedTalkgroups)
{
Alias patchedAlias = getAliasList().getTalkgroupAlias(patchedTalkgroup);
if(patchedAlias != null)
{
patchGroupAlias.addPatchedAlias(patchedAlias);
}
}
}
}
/**
* Removes the temporary patch group alias from the alias list
*/
private void removePatchGroupAlias(String patchGroupID)
{
Alias alias = getAliasList().getTalkgroupAlias(patchGroupID);
if(alias instanceof PatchGroupAlias)
{
PatchGroupAlias patchGroupAlias = (PatchGroupAlias)alias;
getAliasList().removeAlias(patchGroupAlias);
//Replace our temporary patch group alias with the original alias for the patch group ID
if(patchGroupAlias.hasPatchGroupAlias())
{
getAliasList().addAlias(patchGroupAlias.getPatchGroupAlias());
}
}
}
/** /**
* Process a traffic channel allocation message * Process a traffic channel allocation message
*/ */
private void processTSBKChannelGrant(TSBKMessage message) private void processTSBKChannelGrant(TSBKMessage message)
{ {
//Cleanup patch groups - auto-expire any patch groups before we allocate a channel
mPatchGroupManager.cleanupPatchGroups();
String channel = null; String channel = null;
String from = null; String from = null;
String to = null; String to = null;
@@ -3022,7 +2873,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder(CallEventType.DATA_CALL) P25CallEvent event = new P25CallEvent.Builder(CallEventType.DATA_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (gdcg.isTDMAChannel() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(gdcg.getDownlinkFrequency()) .frequency(gdcg.getDownlinkFrequency())
.from(from) .from(from)
@@ -3033,7 +2884,7 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
if(!mIgnoreDataCalls) if(!mIgnoreDataCalls && !gdcg.isTDMAChannel())
{ {
broadcast(new TrafficChannelAllocationEvent(this, broadcast(new TrafficChannelAllocationEvent(this,
mChannelCallMap.get(channel))); mChannelCallMap.get(channel)));
@@ -3060,7 +2911,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder(CallEventType.GROUP_CALL) P25CallEvent event = new P25CallEvent.Builder(CallEventType.GROUP_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (gvcg.isTDMAChannel() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(gvcg.getDownlinkFrequency()) .frequency(gvcg.getDownlinkFrequency())
.from(from) .from(from)
@@ -3071,8 +2922,10 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
broadcast(new TrafficChannelAllocationEvent(this, if(!gvcg.isTDMAChannel())
mChannelCallMap.get(channel))); {
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
}
break; break;
case GROUP_VOICE_CHANNEL_GRANT_UPDATE: case GROUP_VOICE_CHANNEL_GRANT_UPDATE:
GroupVoiceChannelGrantUpdate gvcgu = GroupVoiceChannelGrantUpdate gvcgu =
@@ -3096,8 +2949,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder(CallEventType.GROUP_CALL) P25CallEvent event = new P25CallEvent.Builder(CallEventType.GROUP_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(gvcgu.getChannel1() + (gvcgu.isTDMAChannel1() ? " TDMA" : ""))
.channel(gvcgu.getChannel1())
.details(details.toString()) .details(details.toString())
.frequency(gvcgu.getDownlinkFrequency1()) .frequency(gvcgu.getDownlinkFrequency1())
.from(from) .from(from)
@@ -3108,8 +2960,10 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
broadcast(new TrafficChannelAllocationEvent(this, if(!gvcgu.isTDMAChannel1())
mChannelCallMap.get(channel))); {
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
}
if(gvcgu.hasChannelNumber2()) if(gvcgu.hasChannelNumber2())
{ {
@@ -3130,7 +2984,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event2 = new P25CallEvent.Builder(CallEventType.GROUP_CALL) P25CallEvent event2 = new P25CallEvent.Builder(CallEventType.GROUP_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(gvcgu.getChannel2()) .channel(gvcgu.getChannel2() + (gvcgu.isTDMAChannel2() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(gvcgu.getDownlinkFrequency2()) .frequency(gvcgu.getDownlinkFrequency2())
.to(gvcgu.getGroupAddress2()) .to(gvcgu.getGroupAddress2())
@@ -3140,8 +2994,10 @@ public class P25DecoderState extends DecoderState
broadcast(event2); broadcast(event2);
} }
broadcast(new TrafficChannelAllocationEvent(this, if(!gvcgu.isTDMAChannel2())
mChannelCallMap.get(channel))); {
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
}
} }
break; break;
case GROUP_VOICE_CHANNEL_GRANT_UPDATE_EXPLICIT: case GROUP_VOICE_CHANNEL_GRANT_UPDATE_EXPLICIT:
@@ -3167,7 +3023,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder(CallEventType.GROUP_CALL) P25CallEvent event = new P25CallEvent.Builder(CallEventType.GROUP_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (gvcgue.isTDMAChannel() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(gvcgue.getDownlinkFrequency()) .frequency(gvcgue.getDownlinkFrequency())
.from(from) .from(from)
@@ -3178,8 +3034,10 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
broadcast(new TrafficChannelAllocationEvent(this, if(!gvcgue.isTDMAChannel())
mChannelCallMap.get(channel))); {
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
}
break; break;
case INDIVIDUAL_DATA_CHANNEL_GRANT: case INDIVIDUAL_DATA_CHANNEL_GRANT:
IndividualDataChannelGrant idcg = (IndividualDataChannelGrant)message; IndividualDataChannelGrant idcg = (IndividualDataChannelGrant)message;
@@ -3202,7 +3060,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder(CallEventType.DATA_CALL) P25CallEvent event = new P25CallEvent.Builder(CallEventType.DATA_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (idcg.isTDMAChannel() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(idcg.getDownlinkFrequency()) .frequency(idcg.getDownlinkFrequency())
.from(from) .from(from)
@@ -3213,10 +3071,9 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
if(!mIgnoreDataCalls) if(!mIgnoreDataCalls && !idcg.isTDMAChannel())
{ {
broadcast(new TrafficChannelAllocationEvent(this, broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
mChannelCallMap.get(channel)));
} }
break; break;
case SNDCP_DATA_CHANNEL_GRANT: case SNDCP_DATA_CHANNEL_GRANT:
@@ -3239,7 +3096,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder(CallEventType.DATA_CALL) P25CallEvent event = new P25CallEvent.Builder(CallEventType.DATA_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (sdcg.isTDMAChannel() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(sdcg.getDownlinkFrequency()) .frequency(sdcg.getDownlinkFrequency())
.from(from) .from(from)
@@ -3250,15 +3107,13 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
if(!mIgnoreDataCalls) if(!mIgnoreDataCalls && !sdcg.isTDMAChannel())
{ {
broadcast(new TrafficChannelAllocationEvent(this, broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
mChannelCallMap.get(channel)));
} }
break; break;
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT: case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT:
TelephoneInterconnectVoiceChannelGrant tivcg = TelephoneInterconnectVoiceChannelGrant tivcg = (TelephoneInterconnectVoiceChannelGrant)message;
(TelephoneInterconnectVoiceChannelGrant)message;
channel = tivcg.getChannel(); channel = tivcg.getChannel();
from = null; from = null;
@@ -3282,7 +3137,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder( P25CallEvent event = new P25CallEvent.Builder(
CallEventType.TELEPHONE_INTERCONNECT) CallEventType.TELEPHONE_INTERCONNECT)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (tivcg.isTDMAChannel() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(tivcg.getDownlinkFrequency()) .frequency(tivcg.getDownlinkFrequency())
.from(from) .from(from)
@@ -3293,15 +3148,15 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
broadcast(new TrafficChannelAllocationEvent(this, if(!tivcg.isTDMAChannel())
mChannelCallMap.get(channel))); {
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
}
break; break;
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT_UPDATE: case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT_UPDATE:
TelephoneInterconnectVoiceChannelGrantUpdate tivcgu = TelephoneInterconnectVoiceChannelGrantUpdate tivcgu = (TelephoneInterconnectVoiceChannelGrantUpdate)message;
(TelephoneInterconnectVoiceChannelGrantUpdate)message;
channel = tivcgu.getChannelIdentifier() + "-" + channel = tivcgu.getChannelIdentifier() + "-" + tivcgu.getChannelNumber();
tivcgu.getChannelNumber();
from = null; from = null;
/* Address is ambiguous and could mean either source or target, /* Address is ambiguous and could mean either source or target,
@@ -3324,7 +3179,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder( P25CallEvent event = new P25CallEvent.Builder(
CallEventType.TELEPHONE_INTERCONNECT) CallEventType.TELEPHONE_INTERCONNECT)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (tivcgu.isTDMAChannel() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(tivcgu.getDownlinkFrequency()) .frequency(tivcgu.getDownlinkFrequency())
.from(from) .from(from)
@@ -3335,15 +3190,15 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
broadcast(new TrafficChannelAllocationEvent(this, if(!tivcgu.isTDMAChannel())
mChannelCallMap.get(channel))); {
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
}
break; break;
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT: case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT:
UnitToUnitVoiceChannelGrant uuvcg = UnitToUnitVoiceChannelGrant uuvcg = (UnitToUnitVoiceChannelGrant)message;
(UnitToUnitVoiceChannelGrant)message;
channel = uuvcg.getChannelIdentifier() + "-" + channel = uuvcg.getChannelIdentifier() + "-" + uuvcg.getChannelNumber();
uuvcg.getChannelNumber();
from = uuvcg.getSourceAddress(); from = uuvcg.getSourceAddress();
to = uuvcg.getTargetAddress(); to = uuvcg.getTargetAddress();
@@ -3362,7 +3217,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder( P25CallEvent event = new P25CallEvent.Builder(
CallEventType.UNIT_TO_UNIT_CALL) CallEventType.UNIT_TO_UNIT_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (uuvcg.isTDMAChannel() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(uuvcg.getDownlinkFrequency()) .frequency(uuvcg.getDownlinkFrequency())
.from(from) .from(from)
@@ -3373,15 +3228,15 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
broadcast(new TrafficChannelAllocationEvent(this, if(!uuvcg.isTDMAChannel())
mChannelCallMap.get(channel))); {
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
}
break; break;
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE: case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE:
UnitToUnitVoiceChannelGrantUpdate uuvcgu = UnitToUnitVoiceChannelGrantUpdate uuvcgu = (UnitToUnitVoiceChannelGrantUpdate)message;
(UnitToUnitVoiceChannelGrantUpdate)message;
channel = uuvcgu.getChannelIdentifier() + "-" + channel = uuvcgu.getChannelIdentifier() + "-" + uuvcgu.getChannelNumber();
uuvcgu.getChannelNumber();
from = uuvcgu.getSourceAddress(); from = uuvcgu.getSourceAddress();
to = uuvcgu.getTargetAddress(); to = uuvcgu.getTargetAddress();
@@ -3400,7 +3255,7 @@ public class P25DecoderState extends DecoderState
P25CallEvent event = new P25CallEvent.Builder( P25CallEvent event = new P25CallEvent.Builder(
CallEventType.UNIT_TO_UNIT_CALL) CallEventType.UNIT_TO_UNIT_CALL)
.aliasList(getAliasList()) .aliasList(getAliasList())
.channel(channel) .channel(channel + (uuvcgu.isTDMAChannel() ? " TDMA" : ""))
.details(details.toString()) .details(details.toString())
.frequency(uuvcgu.getDownlinkFrequency()) .frequency(uuvcgu.getDownlinkFrequency())
.from(from) .from(from)
@@ -3411,8 +3266,10 @@ public class P25DecoderState extends DecoderState
broadcast(event); broadcast(event);
} }
broadcast(new TrafficChannelAllocationEvent(this, if(!uuvcgu.isTDMAChannel())
mChannelCallMap.get(channel))); {
broadcast(new TrafficChannelAllocationEvent(this, mChannelCallMap.get(channel)));
}
break; break;
default: default:
break; break;
@@ -3522,29 +3379,25 @@ public class P25DecoderState extends DecoderState
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Activity Summary\n"); sb.append("Activity Summary - Decoder:P25 ").append(getModulation().getLabel()).append("\n");
sb.append("Decoder:\tP25\n"); sb.append(DIVIDER1);
sb.append("===================== THIS SITE ======================"); sb.append("SITE ");
if(mNetworkStatus != null) if(mNetworkStatus != null)
{ {
sb.append("\nNAC:\t" + mNetworkStatus.getNAC()); sb.append("NAC:" + mNetworkStatus.getNAC());
sb.append("\nWACN-SYS:\t" + mNetworkStatus.getWACN()); sb.append("h WACN:" + mNetworkStatus.getWACN());
sb.append("-" + mNetworkStatus.getSystemID()); sb.append("h SYS:" + mNetworkStatus.getSystemID());
sb.append(" ["); sb.append("h [").append(mNetworkStatus.getNetworkCallsign()).append("]");
sb.append(mNetworkStatus.getNetworkCallsign()); sb.append(" LRA:" + mNetworkStatus.getLocationRegistrationArea());
sb.append("]");
sb.append("\nLRA:\t" + mNetworkStatus.getLocationRegistrationArea());
} }
else if(mNetworkStatusExtended != null) else if(mNetworkStatusExtended != null)
{ {
sb.append("\nNAC:\t" + mNetworkStatusExtended.getNAC()); sb.append("NAC:" + mNetworkStatusExtended.getNAC());
sb.append("\nWACN-SYS:\t" + mNetworkStatusExtended.getWACN()); sb.append("h WACN:" + mNetworkStatusExtended.getWACN());
sb.append("-" + mNetworkStatusExtended.getSystemID()); sb.append("h SYS:" + mNetworkStatusExtended.getSystemID());
sb.append(" ["); sb.append("h [").append(mNetworkStatusExtended.getNetworkCallsign()).append("]");
sb.append(mNetworkStatusExtended.getNetworkCallsign()); sb.append(" LRA:" + mNetworkStatusExtended.getLocationRegistrationArea());
sb.append("]");
sb.append("\nLRA:\t" + mNetworkStatusExtended.getLocationRegistrationArea());
} }
String site = null; String site = null;
@@ -3555,11 +3408,10 @@ public class P25DecoderState extends DecoderState
} }
else if(mRFSSStatusMessageExtended != null) else if(mRFSSStatusMessageExtended != null)
{ {
site = mRFSSStatusMessageExtended.getRFSubsystemID() + "-" + site = mRFSSStatusMessageExtended.getRFSubsystemID() + "-" + mRFSSStatusMessageExtended.getSiteID();
mRFSSStatusMessageExtended.getSiteID();
} }
sb.append("\nRFSS-SITE:\t" + site); sb.append("h RFSS-SITE:").append(site).append("h");
if(hasAliasList()) if(hasAliasList())
{ {
@@ -3571,121 +3423,120 @@ public class P25DecoderState extends DecoderState
} }
} }
sb.append("\n").append(DIVIDER2);
if(mNetworkStatus != null) if(mNetworkStatus != null)
{ {
sb.append("\nSERVICES:\t" + SystemService.toString( sb.append("SERVICES: " + SystemService.toString(mNetworkStatus.getSystemServiceClass())).append("\n");
mNetworkStatus.getSystemServiceClass())); sb.append(DIVIDER2);
sb.append("\nPCCH:\tDNLINK " + mFrequencyFormatter.format( sb.append("PCCH DOWNLINK ")
(double)mNetworkStatus.getDownlinkFrequency() / 1E6d) + .append(mFrequencyFormatter.format((double)mNetworkStatus.getDownlinkFrequency() / 1E6d))
" [" + mNetworkStatus.getIdentifier() + "-" + .append(" [").append(mNetworkStatus.getIdentifier()).append("-").append(mNetworkStatus.getChannel())
mNetworkStatus.getChannel() + "]\n"); .append("] UPLINK ")
sb.append("\tUPLINK " + mFrequencyFormatter.format( .append(mFrequencyFormatter.format((double)mNetworkStatus.getUplinkFrequency() / 1E6d))
(double)mNetworkStatus.getUplinkFrequency() / 1E6d) + " [" + .append(" [").append(mNetworkStatus.getIdentifier()).append("-").append(mNetworkStatus.getChannel())
mNetworkStatus.getIdentifier() + "-" + .append("]\n");
mNetworkStatus.getChannel() + "]\n");
} }
else if(mNetworkStatusExtended != null) else if(mNetworkStatusExtended != null)
{ {
sb.append("\nSERVICES:\t" + SystemService.toString( sb.append("\nSERVICES:").append(SystemService.toString(mNetworkStatusExtended.getSystemServiceClass()))
mNetworkStatusExtended.getSystemServiceClass())); .append("\n");
sb.append("\nPCCH:\tDNLINK " + mFrequencyFormatter.format( sb.append(DIVIDER2);
(double)mNetworkStatusExtended.getDownlinkFrequency() / 1E6d) + sb.append("PCCH DOWNLINK ")
" [" + mNetworkStatusExtended.getTransmitIdentifier() + "-" + .append(mFrequencyFormatter.format((double)mNetworkStatusExtended.getDownlinkFrequency() / 1E6d))
mNetworkStatusExtended.getTransmitChannel() + "]\n"); .append(" [").append(mNetworkStatusExtended.getTransmitIdentifier()).append("-")
sb.append("\tUPLINK " + mFrequencyFormatter.format( .append(mNetworkStatusExtended.getTransmitChannel()).append("] UPLINK ")
(double)mNetworkStatusExtended.getUplinkFrequency() / 1E6d) + .append(mFrequencyFormatter.format((double)mNetworkStatusExtended.getUplinkFrequency() / 1E6d))
" [" + mNetworkStatusExtended.getReceiveIdentifier() + "-" + .append(" [").append(mNetworkStatusExtended.getReceiveIdentifier()).append("-")
mNetworkStatusExtended.getReceiveChannel() + "]"); .append(mNetworkStatusExtended.getReceiveChannel()).append("]\n");
} }
if(mSecondaryControlChannels.isEmpty()) if(mSecondaryControlChannels.isEmpty())
{ {
sb.append("\nSCCH:\tNONE"); sb.append("SCCH: NONE\n");
} }
else else
{ {
for(module.decode.p25.message.tsbk.osp.control.SecondaryControlChannelBroadcast for(module.decode.p25.message.tsbk.osp.control.SecondaryControlChannelBroadcast sec : mSecondaryControlChannels)
sec : mSecondaryControlChannels)
{ {
sb.append("\nSCCH:\tDNLINK " + mFrequencyFormatter.format( sb.append("SCCH DOWNLINK ")
(double)sec.getDownlinkFrequency1() / 1E6d) + .append(mFrequencyFormatter.format((double)sec.getDownlinkFrequency1() / 1E6d))
" [" + sec.getIdentifier1() + "-" + sec.getChannel1() + "]\n"); .append(" [").append(sec.getIdentifier1()).append("-").append(sec.getChannel1()).append("] UPLINK ")
sb.append("\tUPLINK " + mFrequencyFormatter.format( .append(mFrequencyFormatter.format((double)sec.getUplinkFrequency1() / 1E6d))
(double)sec.getUplinkFrequency1() / 1E6d) + " [" + .append(" [").append(sec.getIdentifier1()).append("-").append(sec.getChannel1()).append("]");
sec.getIdentifier1() + "-" + sec.getChannel1() + "]\n");
if(sec.hasChannel2()) if(sec.hasChannel2())
{ {
sb.append("\nSCCH:\tDNLINK " + mFrequencyFormatter.format( sb.append(" SCCH 2 DOWNLINK ")
(double)sec.getDownlinkFrequency2() / 1E6d) + .append(mFrequencyFormatter.format((double)sec.getDownlinkFrequency2() / 1E6d))
" [" + sec.getIdentifier2() + "-" + sec.getChannel2() + "]\n"); .append(" [").append(sec.getIdentifier2()).append("-").append(sec.getChannel2())
sb.append("\tUPLINK " + mFrequencyFormatter.format( .append("] UPLINK ").append(mFrequencyFormatter.format((double)sec.getUplinkFrequency2() / 1E6d))
(double)sec.getUplinkFrequency2() / 1E6d) + " [" + .append(" [").append(sec.getIdentifier2()).append("-").append(sec.getChannel2()).append("]");
sec.getIdentifier2() + "-" + sec.getChannel2() + "]");
} }
sb.append("\n");
} }
} }
if(mSNDCPDataChannel != null) if(mSNDCPDataChannel != null)
{ {
sb.append("\nSNDCP:"); sb.append("SNDCP DOWNLINK ")
sb.append("\tDNLINK " + mFrequencyFormatter.format( .append(mFrequencyFormatter.format((double)mSNDCPDataChannel.getDownlinkFrequency() / 1E6D))
(double)mSNDCPDataChannel.getDownlinkFrequency() / 1E6D) + .append(" [").append(mSNDCPDataChannel.getTransmitChannel()).append("]").append(" UPLINK ")
" [" + mSNDCPDataChannel.getTransmitChannel() + "]"); .append(mFrequencyFormatter.format((double)mSNDCPDataChannel.getUplinkFrequency() / 1E6D))
sb.append("\tUPLINK " + mFrequencyFormatter.format( .append(" [").append(mSNDCPDataChannel.getReceiveChannel()).append("]\n");
(double)mSNDCPDataChannel.getUplinkFrequency() / 1E6D) +
" [" + mSNDCPDataChannel.getReceiveChannel() + "]");
} }
if(mProtectionParameterBroadcast != null) if(mProtectionParameterBroadcast != null)
{ {
sb.append("\nENCRYPTION:"); sb.append(DIVIDER2);
sb.append("\nTYPE:\t" + mProtectionParameterBroadcast sb.append("ENCRYPTION TYPE:").append(mProtectionParameterBroadcast.getEncryptionType().name());
.getEncryptionType().name()); sb.append(" ALGORITHM:").append(mProtectionParameterBroadcast.getAlgorithmID());
sb.append("\nALGORITHM:\t" + mProtectionParameterBroadcast sb.append(" KEY:").append(mProtectionParameterBroadcast.getKeyID());
.getAlgorithmID()); sb.append(" INBOUND IV:").append(mProtectionParameterBroadcast.getInboundInitializationVector());
sb.append("\nKEY:\t" + mProtectionParameterBroadcast.getKeyID()); sb.append(" OUTBOUND IV:").append(mProtectionParameterBroadcast.getOutboundInitializationVector());
sb.append("\nINBOUND IV:\t" + mProtectionParameterBroadcast sb.append("\n");
.getInboundInitializationVector());
sb.append("\nOUTBOUND IV:\t" + mProtectionParameterBroadcast
.getOutboundInitializationVector());
} }
List<Integer> identifiers = new ArrayList<>(mBands.keySet()); List<Integer> identifiers = new ArrayList<>(mBands.keySet());
Collections.sort(identifiers); Collections.sort(identifiers);
sb.append("\nFREQUENCY BANDS:"); sb.append(DIVIDER2).append("FREQUENCY BANDS:\n");
for(Integer id : identifiers) for(Integer id : identifiers)
{ {
IBandIdentifier band = mBands.get(id); IBandIdentifier band = mBands.get(id);
sb.append(band.toString()).append("\n");
sb.append("\n\t" + id); // sb.append(" ").append(id);
sb.append("- BASE: " + mFrequencyFormatter.format( // sb.append(" - BASE: " + mFrequencyFormatter.format(
(double)band.getBaseFrequency() / 1E6d)); // (double)band.getBaseFrequency() / 1E6d));
sb.append(" CHANNEL SIZE: " + mFrequencyFormatter.format( // sb.append(" CHANNEL SIZE: " + mFrequencyFormatter.format(
(double)band.getChannelSpacing() / 1E6d)); // (double)band.getChannelSpacing() / 1E6d));
sb.append(" UPLINK OFFSET: " + mFrequencyFormatter.format( // sb.append(" UPLINK OFFSET: " + mFrequencyFormatter.format(
(double)band.getTransmitOffset() / 1E6D)); // (double)band.getTransmitOffset() / 1E6D));
// sb.append("\n");
} }
sb.append("\n\n=================== NEIGHBORS ======================"); sb.append(DIVIDER2).append("NEIGHBOR SITES: ");
if(mNeighborMap.isEmpty()) if(mNeighborMap.isEmpty())
{ {
sb.append("\n\tNONE\n"); sb.append("NONE\n");
sb.append("\n----------------------------------------------------");
} }
else else
{ {
for(IAdjacentSite neighbor : mNeighborMap.values()) for(IAdjacentSite neighbor : mNeighborMap.values())
{ {
sb.append("\nNAC:\t" + ((P25Message)neighbor).getNAC()); sb.append("\n");
sb.append("\nSYSTEM:\t" + neighbor.getSystemID()); sb.append("NAC:").append(((P25Message)neighbor).getNAC());
sb.append("\nLRA:\t" + neighbor.getLRA()); sb.append("h SYSTEM:" + neighbor.getSystemID());
sb.append("h LRA:" + neighbor.getLRA());
String neighborID = neighbor.getRFSS() + "-" + neighbor.getSiteID(); String neighborID = neighbor.getRFSS() + "-" + neighbor.getSiteID();
sb.append("\nRFSS-SITE:\t" + neighborID); sb.append("h RFSS-SITE:" + neighborID);
sb.append("h ");
if(hasAliasList()) if(hasAliasList())
{ {
@@ -3693,18 +3544,16 @@ public class P25DecoderState extends DecoderState
if(siteAlias != null) if(siteAlias != null)
{ {
sb.append(" " + siteAlias.getName()); sb.append(siteAlias.getName());
} }
} }
sb.append("\nPCCH:\tDNLINK " + mFrequencyFormatter.format( sb.append("\n PCCH: DOWNLINK ")
(double)neighbor.getDownlinkFrequency() / 1E6d) + .append(mFrequencyFormatter.format((double)neighbor.getDownlinkFrequency() / 1E6d))
" [" + neighbor.getDownlinkChannel() + "]"); .append(" [").append(neighbor.getDownlinkChannel()).append("] UPLINK:")
sb.append("\n\tUPLINK:" + mFrequencyFormatter.format( .append(mFrequencyFormatter.format((double)neighbor.getUplinkFrequency() / 1E6d))
(double)neighbor.getUplinkFrequency() / 1E6d) + .append(" [").append(neighbor.getDownlinkChannel()).append("] SERVICES: ")
" [" + neighbor.getDownlinkChannel() + "]\n"); .append(neighbor.getSystemServiceClass());
sb.append("\nSERVICES:\t" + neighbor.getSystemServiceClass());
sb.append("\n----------------------------------------------------");
} }
} }

View File

@@ -47,12 +47,10 @@ public class P25_C4FMDecoder extends P25Decoder
private final static Logger mLog = LoggerFactory.getLogger( P25_C4FMDecoder.class ); private final static Logger mLog = LoggerFactory.getLogger( P25_C4FMDecoder.class );
/* Instrumentation Taps */ /* Instrumentation Taps */
private static final String INSTRUMENT_FILTER_OUTPUT = "Tap Point: Pre-Filter Output";
private static final String INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT = "Tap Point: Symbol Filter Output"; private static final String INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT = "Tap Point: Symbol Filter Output";
private static final String INSTRUMENT_C4FM_SLICER_OUTPUT = "Tap Point: C4FM Slicer Output"; private static final String INSTRUMENT_C4FM_SLICER_OUTPUT = "Tap Point: C4FM Slicer Output";
private List<TapGroup> mAvailableTaps; private List<TapGroup> mAvailableTaps;
private RealFIRFilter_RB_RB mC4FMPreFilter;
private C4FMSymbolFilter mSymbolFilter; private C4FMSymbolFilter mSymbolFilter;
private C4FMSlicer mC4FMSlicer; private C4FMSlicer mC4FMSlicer;
private P25MessageFramer mMessageFramer; private P25MessageFramer mMessageFramer;
@@ -74,15 +72,9 @@ public class P25_C4FMDecoder extends P25Decoder
{ {
super( aliasList ); super( aliasList );
/* Filter demodulated sample buffers */
float[] filter = FilterFactory.getLowPass( 48000, 2500, 4000, 80, WindowType.HANNING, true );
mC4FMPreFilter = new RealFIRFilter_RB_RB( filter, 1.0f );
/* Shape gain and frequency offsets to optimize sample stream */ /* Shape gain and frequency offsets to optimize sample stream */
mSymbolFilter = new C4FMSymbolFilter( frequencyCorrectionMaximum ); mSymbolFilter = new C4FMSymbolFilter( frequencyCorrectionMaximum );
mC4FMPreFilter.setListener( mSymbolFilter );
/* Convert samples to symbols */ /* Convert samples to symbols */
mC4FMSlicer = new C4FMSlicer(); mC4FMSlicer = new C4FMSlicer();
mSymbolFilter.setListener( mC4FMSlicer ); mSymbolFilter.setListener( mC4FMSlicer );
@@ -100,9 +92,6 @@ public class P25_C4FMDecoder extends P25Decoder
{ {
super.dispose(); super.dispose();
mC4FMPreFilter.dispose();
mC4FMPreFilter = null;
mSymbolFilter.dispose(); mSymbolFilter.dispose();
mSymbolFilter = null; mSymbolFilter = null;
@@ -121,7 +110,7 @@ public class P25_C4FMDecoder extends P25Decoder
@Override @Override
public Listener<RealBuffer> getFilteredRealBufferListener() public Listener<RealBuffer> getFilteredRealBufferListener()
{ {
return mC4FMPreFilter; return mSymbolFilter;
} }
/** /**
@@ -136,8 +125,6 @@ public class P25_C4FMDecoder extends P25Decoder
TapGroup group = new TapGroup( "P25 C4FM Decoder" ); TapGroup group = new TapGroup( "P25 C4FM Decoder" );
group.add( new FloatBufferTap( INSTRUMENT_FILTER_OUTPUT, 0, 1.0f ) );
group.add( new FloatTap( INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT, 0, 0.1f ) ); group.add( new FloatTap( INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT, 0, 0.1f ) );
group.add( new DibitTap( INSTRUMENT_C4FM_SLICER_OUTPUT, 0, 0.1f ) ); group.add( new DibitTap( INSTRUMENT_C4FM_SLICER_OUTPUT, 0, 0.1f ) );
@@ -165,11 +152,6 @@ public class P25_C4FMDecoder extends P25Decoder
switch( tap.getName() ) switch( tap.getName() )
{ {
case INSTRUMENT_FILTER_OUTPUT:
FloatBufferTap filterOutput = (FloatBufferTap)tap;
mC4FMPreFilter.setListener( filterOutput );
filterOutput.setListener( mSymbolFilter );
break;
case INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT: case INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT:
FloatTap symbolTap = (FloatTap)tap; FloatTap symbolTap = (FloatTap)tap;
mSymbolFilter.setListener( symbolTap ); mSymbolFilter.setListener( symbolTap );
@@ -201,9 +183,6 @@ public class P25_C4FMDecoder extends P25Decoder
switch( tap.getName() ) switch( tap.getName() )
{ {
case INSTRUMENT_FILTER_OUTPUT:
mC4FMPreFilter.setListener( mSymbolFilter );
break;
case INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT: case INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT:
mSymbolFilter.setListener( mC4FMSlicer ); mSymbolFilter.setListener( mC4FMSlicer );
break; break;

View File

@@ -0,0 +1,102 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25;
import java.util.ArrayList;
import java.util.List;
public class PatchGroup
{
private long mExpireThreshold = 5000; //5 seconds
private long mLastUpdated;
private String mPatchGroupID;
private List<String> mPatchedGroups = new ArrayList<>();
/**
* Constructs a patch group with the specified patch group ID
* @param patchGroupID that identifies this patch group
*/
public PatchGroup(String patchGroupID)
{
mPatchGroupID = patchGroupID;
mLastUpdated = System.currentTimeMillis();
}
/**
* Patch group ID for this patch group
*/
public String getPatchGroupID()
{
return mPatchGroupID;
}
/**
* Adds the patched group to this patch group. Duplicate patched groups are ignored.
*
* Note: the patch group ID will not be added as a patched group, to avoid circular dependencies.
*
* @return true if the patched group was added to this patch group
*/
public boolean addPatchedGroup(String patchedGroup)
{
if(patchedGroup != null && !patchedGroup.equals(mPatchGroupID) && !mPatchedGroups.contains(patchedGroup))
{
mPatchedGroups.add(patchedGroup);
return true;
}
return false;
}
/**
* Patched talkgroups that are part of this patch group.
*/
public List<String> getPatchedGroups()
{
return mPatchedGroups;
}
/**
* Updates the timestamp for this patch group.
*/
public void updateTimestamp()
{
mLastUpdated = System.currentTimeMillis();
}
/**
* Indicates if this patch group is expired, meaning that it hasn't been updated in the past (expire
* threshold) seconds.
*/
public boolean isExpired()
{
return System.currentTimeMillis() - mLastUpdated > mExpireThreshold;
}
/**
* Sets the patch group expiration threshold (default = 5000 ms). A patch group is considered expired if
* no new updates have been received within the past (expire threshold) milliseconds
*
* @param expireThreshold in milliseconds
*/
public void setExpireThreshold(long expireThreshold)
{
mExpireThreshold = expireThreshold;
}
}

View File

@@ -0,0 +1,245 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25;
import alias.Alias;
import alias.AliasList;
import alias.PatchGroupAlias;
import alias.id.talkgroup.TalkgroupID;
import module.decode.event.CallEvent;
import sample.Broadcaster;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class PatchGroupManager
{
private AliasList mAliasList;
private List<PatchGroup> mPatchGroups = new ArrayList<>();
private Broadcaster<CallEvent> mCallEventBroadcaster;
/**
* Manages active P25 patch groups and auto-expires patch groups if not updated every 5 seconds.
*
* @param aliasList to keep updated with patch group changes
* @param broadcaster for rebroadcasting patch group related call events
*/
public PatchGroupManager(AliasList aliasList, Broadcaster<CallEvent> broadcaster)
{
mAliasList = aliasList;
mCallEventBroadcaster = broadcaster;
}
/**
* Removes the patch group.
*
* @param patchGroupID of the patch group to remove
*/
public void removePatchGroup(String patchGroupID)
{
removePatchGroup(patchGroupID, false);
}
/**
* Removes the patch group.
*
* @param patchGroupID of the patch group to remove
* @param expired true if the patch group is being removed because it expired, false if we receive a
* message commanding commanding a patch group delete.
*/
private void removePatchGroup(String patchGroupID, boolean expired)
{
PatchGroup patchGroup = getPatchGroup(patchGroupID);
if(patchGroup != null)
{
//Cleanup the alias list
if(mAliasList != null)
{
Alias alias = mAliasList.getTalkgroupAlias(patchGroupID);
if(alias instanceof PatchGroupAlias)
{
PatchGroupAlias patchGroupAlias = (PatchGroupAlias)alias;
mAliasList.removeAlias(patchGroupAlias);
//Replace our temporary patch group alias with the original alias for the patch group ID
if(patchGroupAlias.hasPatchGroupAlias())
{
mAliasList.addAlias(patchGroupAlias.getPatchGroupAlias());
}
}
}
mPatchGroups.remove(patchGroup);
if(mCallEventBroadcaster != null)
{
StringBuilder sb = new StringBuilder();
sb.append((expired ? "EXPIRED " : "DELETED "));
sb.append("PATCH GROUP:").append(patchGroup.getPatchGroupID());
sb.append(" ").append(patchGroup.getPatchedGroups());
mCallEventBroadcaster.broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.PATCH_GROUP_DELETE)
.to(patchGroup.getPatchGroupID())
.details(sb.toString())
.build());
}
}
}
/**
* Adds/updates a patch group alias to the alias list containing aliases for each of the patched talkgroups. If the
* patch group alias already exists, any patched talkgroups will be removed from the existing patch group alias and
* replaced with the aliases corresponding to the patched talkgroup aliases.
*
* @param patchGroupID for the patch group
* @param patchedTalkgroups containing the talkgroup IDs for each of the patched talkgroups
*/
public void updatePatchGroup(String patchGroupID, List<String> patchedTalkgroups)
{
boolean updated = false;
PatchGroup patchGroup = getPatchGroup(patchGroupID);
if(patchGroup == null)
{
//Remove any expired patch groups before we add a new one
cleanupPatchGroups();
patchGroup = new PatchGroup(patchGroupID);
mPatchGroups.add(patchGroup);
updated = true;
}
else
{
patchGroup.updateTimestamp();
}
for(String patchedGroup : patchedTalkgroups)
{
if(patchGroup.addPatchedGroup(patchedGroup))
{
updated = true;
}
}
//If we make any changes to the patch group, update the patch group alias
if(updated)
{
PatchGroupAlias patchGroupAlias = null;
//Check for an existing alias for the patch talkgroup - do not include wildcard aliases
if(mAliasList != null)
{
Alias existingAlias = mAliasList.getTalkgroupAlias(patchGroupID, false);
if(existingAlias instanceof PatchGroupAlias)
{
patchGroupAlias = (PatchGroupAlias)existingAlias;
}
else
{
patchGroupAlias = new PatchGroupAlias();
patchGroupAlias.addAliasID(new TalkgroupID(patchGroupID));
if(existingAlias != null)
{
mAliasList.removeAlias(existingAlias);
patchGroupAlias.setPatchGroupAlias(existingAlias);
}
mAliasList.addAlias(patchGroupAlias);
}
if(patchGroupAlias != null)
{
patchGroupAlias.setPatchedTalkgroupIDs(patchGroup.getPatchedGroups());
patchGroupAlias.clearPatchedAliases();
for(String patchedTalkgroup : patchGroup.getPatchedGroups())
{
Alias patchedAlias = mAliasList.getTalkgroupAlias(patchedTalkgroup);
if(patchedAlias != null)
{
patchGroupAlias.addPatchedAlias(patchedAlias);
}
}
}
}
if(mCallEventBroadcaster != null)
{
StringBuilder sb = new StringBuilder();
sb.append("PATCH GROUP:").append(patchGroup.getPatchGroupID());
sb.append(" ").append(patchGroup.getPatchedGroups());
mCallEventBroadcaster.broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.PATCH_GROUP_ADD)
.aliasList(mAliasList)
.details(sb.toString())
.build());
}
}
}
/**
* Returns the patch group matching the patch group ID or null
*/
private PatchGroup getPatchGroup(String patchGroupID)
{
for(PatchGroup patchGroup : mPatchGroups)
{
if(patchGroup.getPatchGroupID().equals(patchGroupID))
{
return patchGroup;
}
}
return null;
}
/**
* Checks the last updated timestamp on all patch groups and removes any patch groups that have not been
* updated in the past 5 seconds
*/
public void cleanupPatchGroups()
{
Iterator<PatchGroup> it = mPatchGroups.iterator();
while(it.hasNext())
{
PatchGroup patchGroup = it.next();
if(patchGroup.isExpired())
{
it.remove();
removePatchGroup(patchGroup.getPatchGroupID(), true);
}
}
}
}

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message; package module.decode.p25.message;
public interface IBandIdentifier public interface IBandIdentifier
@@ -29,4 +47,18 @@ public interface IBandIdentifier
*/ */
public abstract long getTransmitOffset(); public abstract long getTransmitOffset();
/**
* Downlink (tower to mobile) Frequency for the specified channel
*/
public abstract long getDownlinkFrequency(int channelNumber);
/**
* Uplink (mobile to tower) Frequency for the specified channel
*/
public abstract long getUplinkFrequency(int channelNumber);
/**
* Indicates if this band is an FDMA (false) or TDMA (true) band
*/
public boolean isTDMA();
} }

View File

@@ -1,214 +1,188 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message; package module.decode.p25.message;
import java.text.SimpleDateFormat;
import map.Plottable;
import message.Message;
import module.decode.p25.reference.DataUnitID;
import alias.Alias; import alias.Alias;
import alias.AliasList; import alias.AliasList;
import bits.BinaryMessage; import bits.BinaryMessage;
import edac.CRC; import edac.CRC;
import map.Plottable;
import message.Message;
import module.decode.p25.reference.DataUnitID;
import java.text.SimpleDateFormat;
public class P25Message extends Message public class P25Message extends Message
{ {
public enum DuplexMode { HALF, FULL }; public enum DuplexMode {HALF, FULL};
public enum SessionMode { PACKET, CIRCUIT }; public enum SessionMode {PACKET, CIRCUIT};
public static final int[] NAC = { 0,1,2,3,4,5,6,7,8,9,10,11 }; public static final int[] NAC = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
public static final int[] DUID = { 12,13,14,15 }; public static final int[] DUID = {12, 13, 14, 15};
public static final int[] BCH = { 16,17,18,19,20,21,22,23,24,25,26,27,28,29, public static final int[] BCH = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
54,55,56,57,58,59,60,61,62,63 };
protected SimpleDateFormat mTimeDurationFormat = new SimpleDateFormat("HH:mm:ss.SSS");
protected SimpleDateFormat mTimeDurationFormat =
new SimpleDateFormat( "HH:mm:ss.SSS"); protected BinaryMessage mMessage;
protected DataUnitID mDUID;
protected BinaryMessage mMessage; protected AliasList mAliasList;
protected DataUnitID mDUID;
protected AliasList mAliasList; protected CRC[] mCRC;
protected CRC[] mCRC; public P25Message(BinaryMessage message, DataUnitID duid, AliasList aliasList)
{
public P25Message( BinaryMessage message, super();
DataUnitID duid,
AliasList aliasList ) mMessage = message;
{ mDUID = duid;
super(); mAliasList = aliasList;
}
mMessage = message;
mDUID = duid; public CRC[] getCRCResults()
mAliasList = aliasList; {
} return mCRC;
}
public CRC[] getCRCResults()
{ public BinaryMessage getSourceMessage()
return mCRC; {
} return mMessage;
}
public BinaryMessage getSourceMessage()
{ public AliasList getAliasList()
return mMessage; {
} return mAliasList;
}
public AliasList getAliasList()
{ public String getNAC()
return mAliasList; {
} return mMessage.getHex(NAC, 3);
}
public String getNAC()
{ public DataUnitID getDUID()
return mMessage.getHex( NAC, 3 ); {
} return mDUID;
}
public DataUnitID getDUID()
{ @Override
return mDUID;
}
@Override
public String getErrorStatus() public String getErrorStatus()
{ {
if( mCRC == null ) if(mCRC == null)
{ {
return "UNKNOWN"; return "UNKNOWN";
} }
return CRC.format( mCRC ); return CRC.format(mCRC);
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( "NAC:" ); sb.append("NAC:");
sb.append( getNAC() ); sb.append(getNAC());
sb.append( " " ); sb.append(" ");
sb.append( getDUID().getLabel() ); sb.append(getDUID().getLabel());
sb.append( " DATA UNIT ID:" + mMessage.getInt( DUID ) ); sb.append(" DATA UNIT ID:" + mMessage.getInt(DUID));
return sb.toString(); return sb.toString();
} }
@Override @Override
public String getBinaryMessage() public String getBinaryMessage()
{ {
return mMessage.toString(); return mMessage.toString();
} }
@Override @Override
public String getProtocol() public String getProtocol()
{ {
return "P25 Phase 1"; return "P25 Phase 1";
} }
@Override @Override
public String getEventType() public String getEventType()
{ {
return mDUID.name(); return mDUID.name();
} }
@Override @Override
public String getFromID() public String getFromID()
{ {
return null;
}
@Override
public Alias getFromIDAlias()
{
if( mAliasList != null )
{
return mAliasList.getTalkgroupAlias( getFromID() );
}
return null; return null;
} }
@Override @Override
public Alias getFromIDAlias()
{
if(mAliasList != null)
{
return mAliasList.getTalkgroupAlias(getFromID());
}
return null;
}
@Override
public String getToID() public String getToID()
{ {
return null; return null;
} }
@Override @Override
public Alias getToIDAlias() public Alias getToIDAlias()
{ {
if( mAliasList != null ) if(mAliasList != null)
{ {
return mAliasList.getTalkgroupAlias( getToID() ); return mAliasList.getTalkgroupAlias(getToID());
} }
return null; return null;
} }
@Override @Override
public Plottable getPlottable() public Plottable getPlottable()
{ {
return null; return null;
} }
@Override @Override
public String toString() public String toString()
{ {
return getMessage(); return getMessage();
} }
@Override @Override
public boolean isValid() public boolean isValid()
{ {
if( mCRC != null ) if(mCRC != null)
{ {
for( CRC crc: mCRC ) for(CRC crc : mCRC)
{ {
if( crc == CRC.FAILED_CRC ) if(crc == CRC.FAILED_CRC)
{ {
return false; return false;
} }
} }
} }
return true;
}
/** return true;
* Calculates the frequency of the uplink channel using the channel number }
* and the IdentifierUpdate message.
*
* @param iden - Identifier Update message
* @param channel - channel number
* @return - frequency in Hertz
*/
protected static long calculateUplink( IBandIdentifier iden, int channel )
{
long downlink = calculateDownlink( iden, channel );
if( downlink > 0 && iden != null )
{
return downlink + iden.getTransmitOffset();
}
return 0;
}
/**
* Calculates the frequency of the downlink channel using the channel number
* and the IdentifierUpdate message.
*
* @param iden - Identifier Update message
* @param channel - channel number
* @return - frequency in Hertz
*/
protected static long calculateDownlink( IBandIdentifier iden, int channel )
{
if( iden != null )
{
return iden.getBaseFrequency() +
( channel * iden.getChannelSpacing() );
}
return 0;
}
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IAdjacentSite; import module.decode.p25.message.IAdjacentSite;
@@ -7,142 +25,148 @@ import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
public class AdjacentSiteStatusBroadcast extends LDU1Message public class AdjacentSiteStatusBroadcast extends LDU1Message implements IdentifierReceiver, IAdjacentSite
implements IdentifierReceiver, IAdjacentSite
{ {
public static final int[] LRA = { 364,365,366,367,372,373,374,375 }; public static final int[] LRA = {364, 365, 366, 367, 372, 373, 374, 375};
public static final int[] SYSTEM_ID = { 384,385,386,387,536,537,538,539,540, public static final int[] SYSTEM_ID = {384, 385, 386, 387, 536, 537, 538, 539, 540, 541, 546, 547};
541,546,547 }; public static final int[] RFSS_ID = {548, 549, 550, 551, 556, 557, 558, 559};
public static final int[] RFSS_ID = { 548,549,550,551,556,557,558,559 }; public static final int[] SITE_ID = {560, 561, 566, 567, 568, 569, 570, 571};
public static final int[] SITE_ID = { 560,561,566,567,568,569,570,571 }; public static final int[] IDENTIFIER = {720, 721, 722, 723};
public static final int[] IDENTIFIER = { 720,721,722,723 }; public static final int[] CHANNEL = {724, 725, 730, 731, 732, 733, 734, 735, 740, 741, 742, 743};
public static final int[] CHANNEL = { 724,725,730,731,732,733,734,735,740, public static final int[] SYSTEM_SERVICE_CLASS = {744, 745, 750, 751, 752, 753, 754, 755};
741,742,743 };
public static final int[] SYSTEM_SERVICE_CLASS = { 744,745,750,751,752,753, private IBandIdentifier mIdentifierUpdate;
754,755 };
public AdjacentSiteStatusBroadcast(LDU1Message message)
private IBandIdentifier mIdentifierUpdate; {
super(message);
public AdjacentSiteStatusBroadcast( LDU1Message message ) }
{
super( message );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST.getDescription(); return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLRA() );
sb.append( " SYS:" + getSystemID() ); sb.append(getMessageStub());
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() ); sb.append(" LRA:" + getLRA());
sb.append( " CHAN:" + getChannel() ); sb.append(" SYS:" + getSystemID());
sb.append(" SITE:" + getRFSS() + "-" + getSiteID());
sb.append(" CHAN:" + getChannel());
sb.append(" " + getSystemServiceClass());
return sb.toString();
}
sb.append( " " + getSystemServiceClass() );
return sb.toString();
}
public String getUniqueID() public String getUniqueID()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getSystemID() );
sb.append( ":" );
sb.append( getRFSS() );
sb.append( ":" );
sb.append( getSiteID() );
return sb.toString();
}
public String getLRA()
{
return mMessage.getHex( LRA, 2 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSS()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public String getSystemServiceClass()
{
return SystemService.toString( mMessage.getInt( SYSTEM_SERVICE_CLASS ) );
}
@Override sb.append(getSystemID());
public void setIdentifierMessage( int identifier, IBandIdentifier message ) sb.append(":");
sb.append(getRFSS());
sb.append(":");
sb.append(getSiteID());
return sb.toString();
}
public String getLRA()
{ {
mIdentifierUpdate = message; return mMessage.getHex(LRA, 2);
} }
@Override public String getSystemID()
{
return mMessage.getHex(SYSTEM_ID, 3);
}
public String getRFSS()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getIdentifier()
{
return mMessage.getInt(IDENTIFIER);
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getChannelNumber()
{
return mMessage.getInt(CHANNEL);
}
public String getSystemServiceClass()
{
return SystemService.toString(mMessage.getInt(SYSTEM_SERVICE_CLASS));
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
mIdentifierUpdate = message;
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getIdentifier(); identifiers[0] = getIdentifier();
return identifiers; return identifiers;
} }
@Override @Override
public String getDownlinkChannel() public String getDownlinkChannel()
{
return getChannel();
}
@Override
public String getUplinkChannel()
{
return getChannel();
}
public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdate, getChannelNumber() ); return getChannel();
} }
@Override
public String getUplinkChannel()
{
return getChannel();
}
public long getDownlinkFrequency()
{
if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getDownlinkFrequency(getChannelNumber());
}
return 0;
}
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getUplinkFrequency(getChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IAdjacentSite; import module.decode.p25.message.IAdjacentSite;
@@ -6,154 +24,160 @@ import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.ldu.LDU1Message; import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
public class AdjacentSiteStatusBroadcastExplicit extends LDU1Message public class AdjacentSiteStatusBroadcastExplicit extends LDU1Message implements IdentifierReceiver, IAdjacentSite
implements IdentifierReceiver, IAdjacentSite
{ {
public static final int[] LRA = { 364,365,366,367,372,373,374,375 }; public static final int[] LRA = {364, 365, 366, 367, 372, 373, 374, 375};
public static final int[] TRANSMIT_IDENTIFIER = { 376,377,382,383 }; public static final int[] TRANSMIT_IDENTIFIER = {376, 377, 382, 383};
public static final int[] TRANSMIT_CHANNEL = { 384,385,386,387,536,537,538, public static final int[] TRANSMIT_CHANNEL = {384, 385, 386, 387, 536, 537, 538, 539, 540, 541, 546, 547};
539,540,541,546,547 }; public static final int[] RFSS_ID = {548, 549, 550, 551, 556, 557, 558, 559};
public static final int[] RFSS_ID = { 548,549,550,551,556,557,558,559 }; public static final int[] SITE_ID = {560, 561, 566, 567, 568, 569, 570, 571};
public static final int[] SITE_ID = { 560,561,566,567,568,569,570,571 }; public static final int[] RECEIVE_IDENTIFIER = {720, 721, 722, 723};
public static final int[] RECEIVE_CHANNEL = {724, 725, 730, 731, 732, 733, 734, 735, 740, 741, 742, 743};
public static final int[] RECEIVE_IDENTIFIER = { 720,721,722,723 };
public static final int[] RECEIVE_CHANNEL = { 724,725,730,731,732,733,734, private IBandIdentifier mTransmitBand;
735,740,741,742,743 }; private IBandIdentifier mReceiveBand;
private IBandIdentifier mTransmitBand; public AdjacentSiteStatusBroadcastExplicit(LDU1Message message)
private IBandIdentifier mReceiveBand; {
super(message);
public AdjacentSiteStatusBroadcastExplicit( LDU1Message message ) }
{
super( message );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT.getDescription(); return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append(getMessageStub());
sb.append( " LRA:" + getLRA() ); sb.append(" LRA:" + getLRA());
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() ); sb.append(" SITE:" + getRFSS() + "-" + getSiteID());
sb.append( " DNLINK:" + getDownlinkChannel() ); sb.append(" DNLINK:" + getDownlinkChannel());
sb.append( " UPLINK:" + getUplinkChannel() ); sb.append(" UPLINK:" + getUplinkChannel());
return sb.toString(); return sb.toString();
} }
public String getUniqueID() public String getUniqueID()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getSystemID() );
sb.append( ":" );
sb.append( getRFSS() );
sb.append( ":" );
sb.append( getSiteID() );
return sb.toString();
}
public String getLRA()
{
return mMessage.getHex( LRA, 2 );
}
public String getRFSS()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSystemID()
{
return "***";
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannel()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getDownlinkChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannel();
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannel()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getUplinkChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannel();
}
@Override sb.append(getSystemID());
public String getSystemServiceClass() sb.append(":");
{ sb.append(getRFSS());
return "[]"; sb.append(":");
} sb.append(getSiteID());
return sb.toString();
}
public String getLRA()
{
return mMessage.getHex(LRA, 2);
}
public String getRFSS()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSystemID()
{
return "***";
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getTransmitIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannel()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public String getDownlinkChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannel();
}
public int getReceiveIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannel()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public String getUplinkChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannel();
}
@Override
public String getSystemServiceClass()
{
return "[]";
}
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitBand, getTransmitChannel() ); if(mTransmitBand != null)
{
return mTransmitBand.getDownlinkFrequency(getTransmitChannel());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveBand, getReceiveChannel() ); if(mReceiveBand != null)
{
return mReceiveBand.getUplinkFrequency(getReceiveChannel());
}
return 0;
} }
@Override @Override
public void setIdentifierMessage( int identifier, IBandIdentifier message ) public void setIdentifierMessage(int identifier, IBandIdentifier message)
{ {
if( identifier == getTransmitIdentifier() ) if(identifier == getTransmitIdentifier())
{ {
mTransmitBand = message; mTransmitBand = message;
} }
if( identifier == getReceiveIdentifier() ) if(identifier == getReceiveIdentifier())
{ {
mReceiveBand = message; mReceiveBand = message;
} }
} }
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[2];
identifiers[0] = getTransmitIdentifier();
identifiers[1] = getReceiveIdentifier();
return identifiers;
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 2 ];
identifiers[ 0 ] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier();
return identifiers;
}
} }

View File

@@ -1,83 +1,118 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.ldu.LDU1Message; import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
public class ChannelIdentifierUpdate extends LDU1Message public class ChannelIdentifierUpdate extends LDU1Message implements IBandIdentifier
implements IBandIdentifier
{ {
public static final int[] IDENTIFIER = { 364,365,366,367 }; public static final int[] IDENTIFIER = {364, 365, 366, 367};
public static final int[] BANDWIDTH = { 372,373,374,375,376,377,382,383,384 }; public static final int[] BANDWIDTH = {372, 373, 374, 375, 376, 377, 382, 383, 384};
public static final int[] TRANSMIT_OFFSET = { 385,386,387,536,537,538,539, public static final int[] TRANSMIT_OFFSET = {385, 386, 387, 536, 537, 538, 539,
540,541 }; 540, 541};
public static final int[] CHANNEL_SPACING = { 546,547,548,549,550,551,556, public static final int[] CHANNEL_SPACING = {546, 547, 548, 549, 550, 551, 556,
557,558,559 }; 557, 558, 559};
public static final int[] BASE_FREQUENCY = { 560,561,566,567,568,569,570, public static final int[] BASE_FREQUENCY = {560, 561, 566, 567, 568, 569, 570,
571,720,721,722,723,724,725,730,731,732,733,734,735,740,741,742,743,744, 571, 720, 721, 722, 723, 724, 725, 730, 731, 732, 733, 734, 735, 740, 741, 742, 743, 744,
745,750,751,752,753,754,755 }; 745, 750, 751, 752, 753, 754, 755};
public ChannelIdentifierUpdate(LDU1Message message)
{
super(message);
}
public ChannelIdentifierUpdate( LDU1Message message )
{
super( message );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE.getDescription(); return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " IDEN:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() ); sb.append(getMessageStub());
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() );
return sb.toString();
}
@Override sb.append(" IDEN:" + getIdentifier());
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
/** sb.append(" BASE:" + getBaseFrequency());
sb.append(" BW:" + getBandwidth());
sb.append(" SPACING:" + getChannelSpacing());
sb.append(" OFFSET:" + getTransmitOffset());
return sb.toString();
}
@Override
public int getIdentifier()
{
return mMessage.getInt(IDENTIFIER);
}
/**
* Channel bandwidth in hertz * Channel bandwidth in hertz
*/ */
@Override @Override
public int getBandwidth() public int getBandwidth()
{ {
return mMessage.getInt( BANDWIDTH ) * 125; return mMessage.getInt(BANDWIDTH) * 125;
} }
@Override @Override
public long getChannelSpacing() public long getChannelSpacing()
{ {
return mMessage.getLong( CHANNEL_SPACING ) * 125l; return mMessage.getLong(CHANNEL_SPACING) * 125l;
} }
@Override @Override
public long getBaseFrequency() public long getBaseFrequency()
{ {
return mMessage.getLong( BASE_FREQUENCY ) * 5l; return mMessage.getLong(BASE_FREQUENCY) * 5l;
} }
@Override @Override
public long getTransmitOffset() public long getTransmitOffset()
{ {
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l; return -1 * mMessage.getLong(TRANSMIT_OFFSET) * 250000l;
}
@Override
public long getDownlinkFrequency(int channelNumber)
{
return getBaseFrequency() + (channelNumber * getChannelSpacing());
}
@Override
public long getUplinkFrequency(int channelNumber)
{
return getDownlinkFrequency(channelNumber) + getTransmitOffset();
}
@Override
public boolean isTDMA()
{
return false;
} }
} }

View File

@@ -4,8 +4,7 @@ import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.ldu.LDU1Message; import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
public class ChannelIdentifierUpdateExplicit extends LDU1Message public class ChannelIdentifierUpdateExplicit extends LDU1Message implements IBandIdentifier
implements IBandIdentifier
{ {
public static final int[] IDENTIFIER = { 364,365,366,367 }; public static final int[] IDENTIFIER = { 364,365,366,367 };
public static final int[] BANDWIDTH = { 372,373,374,375 }; public static final int[] BANDWIDTH = { 372,373,374,375 };
@@ -80,4 +79,22 @@ public class ChannelIdentifierUpdateExplicit extends LDU1Message
{ {
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l; return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l;
} }
@Override
public long getDownlinkFrequency(int channelNumber)
{
return getBaseFrequency() + ( channelNumber * getChannelSpacing() );
}
@Override
public long getUplinkFrequency(int channelNumber)
{
return getDownlinkFrequency(channelNumber) + getTransmitOffset();
}
@Override
public boolean isTDMA()
{
return false;
}
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -5,156 +23,167 @@ import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.ldu.LDU1Message; import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; public class GroupVoiceChannelUpdate extends LDU1Message implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class GroupVoiceChannelUpdate extends LDU1Message
implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] IDENTIFIER_A = {364, 365, 366, 367};
LoggerFactory.getLogger( GroupVoiceChannelUpdate.class ); public static final int[] CHANNEL_A = {372, 373, 374, 375, 376, 377, 382, 383, 384, 385, 386, 387};
public static final int[] GROUP_ADDRESS_A = {536, 537, 538, 539, 540, 541, 546, 547, 548, 549, 550, 551, 556, 557,
558, 559};
public static final int[] IDENTIFIER_B = {560, 561, 566, 567};
public static final int[] CHANNEL_B = {568, 569, 570, 571, 720, 721, 722, 723, 724, 725, 730, 731};
public static final int[] GROUP_ADDRESS_B = {732, 733, 734, 735, 740, 741, 742, 743, 744, 745, 750, 751, 752, 753,
754, 755};
private IBandIdentifier mIdentifierUpdateA;
private IBandIdentifier mIdentifierUpdateB;
public GroupVoiceChannelUpdate(LDU1Message message)
{
super(message);
}
public static final int[] IDENTIFIER_A = { 364,365,366,367 };
public static final int[] CHANNEL_A = { 372,373,374,375,376,377,382,383,384,
385,386,387 };
public static final int[] GROUP_ADDRESS_A = { 536,537,538,539,540,541,546,
547,548,549,550,551,556,557,558,559 };
public static final int[] IDENTIFIER_B = { 560,561,566,567 };
public static final int[] CHANNEL_B = { 568,569,570,571,720,721,722,723,724,
725,730,731 };
public static final int[] GROUP_ADDRESS_B = { 732,733,734,735,740,741,742,
743,744,745,750,751,752,753,754,755 };
private IBandIdentifier mIdentifierUpdateA;
private IBandIdentifier mIdentifierUpdateB;
public GroupVoiceChannelUpdate( LDU1Message message )
{
super( message );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE.getDescription(); return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append(getMessageStub());
sb.append( " CHAN A:" + getChannelA() ); sb.append(" CHAN A:" + getChannelA());
sb.append( " GRP A:" + getGroupAddressA() ); sb.append(" GRP A:" + getGroupAddressA());
if( hasChannelB() ) if(hasChannelB())
{ {
sb.append( " CHAN B:" + getChannelA() ); sb.append(" CHAN B:" + getChannelA());
sb.append( " GRP B:" + getGroupAddressA() ); sb.append(" GRP B:" + getGroupAddressA());
} }
return sb.toString(); return sb.toString();
} }
public int getChannelIdentifierA()
{
return mMessage.getInt(IDENTIFIER_A);
}
public int getChannelIdentifierA()
{
return mMessage.getInt( IDENTIFIER_A );
}
public int getChannelNumberA() public int getChannelNumberA()
{ {
return mMessage.getInt( CHANNEL_A ); return mMessage.getInt(CHANNEL_A);
} }
public String getChannelA() public String getChannelA()
{ {
return getChannelIdentifierA() + "-" + getChannelNumberA(); return getChannelIdentifierA() + "-" + getChannelNumberA();
} }
public int getChannelIdentifierB() public int getChannelIdentifierB()
{ {
return mMessage.getInt( IDENTIFIER_B ); return mMessage.getInt(IDENTIFIER_B);
} }
public int getChannelNumberB() public int getChannelNumberB()
{ {
return mMessage.getInt( CHANNEL_B ); return mMessage.getInt(CHANNEL_B);
} }
public String getChannelB() public String getChannelB()
{ {
return getChannelIdentifierB() + "-" + getChannelNumberB(); return getChannelIdentifierB() + "-" + getChannelNumberB();
} }
public boolean hasChannelB() public boolean hasChannelB()
{ {
return getChannelNumberB() != 0; return getChannelNumberB() != 0;
} }
public String getGroupAddressA() public String getGroupAddressA()
{ {
return mMessage.getHex( GROUP_ADDRESS_A, 4 ); return mMessage.getHex(GROUP_ADDRESS_A, 4);
} }
public String getGroupAddressB() public String getGroupAddressB()
{ {
return mMessage.getHex( GROUP_ADDRESS_B, 4 ); return mMessage.getHex(GROUP_ADDRESS_B, 4);
} }
@Override @Override
public void setIdentifierMessage( int identifier, IBandIdentifier message ) public void setIdentifierMessage(int identifier, IBandIdentifier message)
{ {
if( identifier == getChannelIdentifierA() ) if(identifier == getChannelIdentifierA())
{ {
mIdentifierUpdateA = message; mIdentifierUpdateA = message;
} }
if( identifier == getChannelIdentifierB() ) if(identifier == getChannelIdentifierB())
{ {
mIdentifierUpdateB = message; mIdentifierUpdateB = message;
} }
} }
@Override @Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
if( hasChannelB() ) if(hasChannelB())
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getChannelIdentifierA(); identifiers[0] = getChannelIdentifierA();
identifiers[ 1 ] = getChannelIdentifierB(); identifiers[1] = getChannelIdentifierB();
return identifiers; return identifiers;
} }
else else
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getChannelIdentifierA(); identifiers[0] = getChannelIdentifierA();
return identifiers; return identifiers;
} }
} }
public long getDownlinkFrequencyA() public long getDownlinkFrequencyA()
{ {
return calculateDownlink( mIdentifierUpdateA, getChannelNumberA() ); if(mIdentifierUpdateA != null)
{
return mIdentifierUpdateA.getDownlinkFrequency(getChannelNumberA());
}
return 0;
} }
public long getUplinkFrequencyA() public long getUplinkFrequencyA()
{ {
return calculateUplink( mIdentifierUpdateA, getChannelNumberA() ); if(mIdentifierUpdateA != null)
{
return mIdentifierUpdateA.getUplinkFrequency(getChannelNumberA());
}
return 0;
} }
public long getDownlinkFrequencyB() public long getDownlinkFrequencyB()
{ {
return calculateDownlink( mIdentifierUpdateB, getChannelNumberA() ); if(mIdentifierUpdateB != null)
{
return mIdentifierUpdateB.getDownlinkFrequency(getChannelNumberB());
}
return 0;
} }
public long getUplinkFrequencyB() public long getUplinkFrequencyB()
{ {
return calculateUplink( mIdentifierUpdateB, getChannelNumberA() ); if(mIdentifierUpdateB != null)
{
return mIdentifierUpdateB.getUplinkFrequency(getChannelNumberB());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -5,151 +23,149 @@ import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.ldu.LDU1Message; import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; public class GroupVoiceChannelUpdateExplicit extends LDU1Message implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class GroupVoiceChannelUpdateExplicit extends LDU1Message
implements IdentifierReceiver
{ {
private final static Logger mLog =
LoggerFactory.getLogger( GroupVoiceChannelUpdateExplicit.class );
public static final int EMERGENCY_FLAG = 376; public static final int EMERGENCY_FLAG = 376;
public static final int ENCRYPTED_CHANNEL_FLAG = 377; public static final int ENCRYPTED_CHANNEL_FLAG = 377;
public static final int DUPLEX_MODE = 382; public static final int DUPLEX_MODE = 382;
public static final int SESSION_MODE = 383; public static final int SESSION_MODE = 383;
public static final int[] GROUP_ADDRESS = { 536,537,538,539,540,541,546,547, public static final int[] GROUP_ADDRESS = {536, 537, 538, 539, 540, 541, 546, 547, 548, 549, 550, 551, 556, 557, 558, 559};
548,549,550,551,556,557,558,559 }; public static final int[] TRANSMIT_IDENTIFIER = {560, 561, 566, 567};
public static final int[] TRANSMIT_IDENTIFIER = { 560,561,566,567 }; public static final int[] TRANSMIT_CHANNEL = {568, 569, 570, 571, 720, 721, 722, 723, 724, 725, 730, 731};
public static final int[] TRANSMIT_CHANNEL = { 568,569,570,571,720,721,722, public static final int[] RECEIVE_IDENTIFIER = {732, 733, 734, 735};
723,724,725,730,731 }; public static final int[] RECEIVE_CHANNEL = {740, 741, 742, 743, 744, 745, 750, 751, 752, 753, 754, 755};
public static final int[] RECEIVE_IDENTIFIER = { 732,733,734,735 };
public static final int[] RECEIVE_CHANNEL = { 740,741,742,743,744,745,750, private IBandIdentifier mTransmitIdentifierUpdate;
751,752,753,754,755 }; private IBandIdentifier mReceiveIdentifierUpdate;
public GroupVoiceChannelUpdateExplicit(LDU1Message message)
{
super(message);
}
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public GroupVoiceChannelUpdateExplicit( LDU1Message message )
{
super( message );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT.getDescription(); return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
if( isEncryptedChannel() )
{
sb.append( " ENCRYPTED CHANNEL" );
}
sb.append(getMessageStub());
return sb.toString();
} if(isEmergency())
{
sb.append(" EMERGENCY");
}
if(isEncryptedChannel())
{
sb.append(" ENCRYPTED CHANNEL");
}
return sb.toString();
}
public boolean isEmergency() public boolean isEmergency()
{ {
return mMessage.get( EMERGENCY_FLAG ); return mMessage.get(EMERGENCY_FLAG);
} }
public boolean isEncryptedChannel() public boolean isEncryptedChannel()
{ {
return mMessage.get( ENCRYPTED_CHANNEL_FLAG ); return mMessage.get(ENCRYPTED_CHANNEL_FLAG);
} }
public DuplexMode getDuplexMode() public DuplexMode getDuplexMode()
{ {
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF; return mMessage.get(DUPLEX_MODE) ? DuplexMode.FULL : DuplexMode.HALF;
} }
public SessionMode getSessionMode() public SessionMode getSessionMode()
{ {
return mMessage.get( SESSION_MODE ) ? return mMessage.get(SESSION_MODE) ?
SessionMode.CIRCUIT : SessionMode.PACKET; SessionMode.CIRCUIT : SessionMode.PACKET;
} }
public int getTransmitChannelIdentifier() public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{ {
return mMessage.getInt( TRANSMIT_CHANNEL ); return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitChannelIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveChannelIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
} }
@Override public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public String getGroupAddress()
{
return mMessage.getHex(GROUP_ADDRESS, 4);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitChannelIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveChannelIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitChannelIdentifier(); identifiers[0] = getTransmitChannelIdentifier();
identifiers[ 1 ] = getReceiveChannelIdentifier(); identifiers[1] = getReceiveChannelIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitIdentifierUpdate, if(mTransmitIdentifierUpdate != null)
getTransmitChannelNumber() ); {
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveIdentifierUpdate, if(mReceiveIdentifierUpdate != null)
getReceiveChannelNumber() ); {
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -6,105 +24,106 @@ import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import module.decode.p25.reference.Service; import module.decode.p25.reference.Service;
import org.slf4j.Logger; public class NetworkStatusBroadcast extends LDU1Message implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class NetworkStatusBroadcast extends LDU1Message
implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] NETWORK_ID = {376, 377, 382, 383, 384, 385, 386, 387, 536, 537, 538, 539, 540, 541, 546,
LoggerFactory.getLogger( NetworkStatusBroadcast.class ); 547, 548, 549, 550, 551};
public static final int[] NETWORK_ID = { 376,377,382,383,384,385,386,387, public static final int[] SYSTEM_ID = {556, 557, 558, 559, 560, 561, 566, 567, 568, 569, 570, 571};
536,537,538,539,540,541,546,547,548,549,550,551 }; public static final int[] IDENTIFIER = {720, 721, 722, 723};
public static final int[] SYSTEM_ID = { 556,557,558,559,560,561,566,567,568, public static final int[] CHANNEL = {724, 725, 730, 731, 732, 733, 734, 735, 740, 741, 742, 743};
569,570,571 }; public static final int[] SYSTEM_SERVICE_CLASS = {744, 745, 750, 751, 752, 753, 754, 755};
public static final int[] IDENTIFIER = { 720,721,722,723 };
public static final int[] CHANNEL = { 724,725,730,731,732,733,734,735,740, private IBandIdentifier mIdentifierUpdate;
741,742,743 };
public static final int[] SYSTEM_SERVICE_CLASS = { 744,745,750,751,752,753, public NetworkStatusBroadcast(LDU1Message source)
754,755 }; {
super(source);
private IBandIdentifier mIdentifierUpdate; }
public NetworkStatusBroadcast( LDU1Message source )
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.NETWORK_STATUS_BROADCAST.getDescription(); return LinkControlOpcode.NETWORK_STATUS_BROADCAST.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " NETWORK:" + getNetworkID() );
sb.append( " SYS:" + getSystem() );
sb.append( " CHAN:" + getChannel() );
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
return sb.toString();
}
public String getNetworkID()
{
return mMessage.getHex( NETWORK_ID, 5 );
}
public String getSystem()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
mIdentifierUpdate = message; StringBuilder sb = new StringBuilder();
sb.append(getMessageStub());
sb.append(" NETWORK:" + getNetworkID());
sb.append(" SYS:" + getSystem());
sb.append(" CHAN:" + getChannel());
sb.append(" " + Service.getServices(getSystemServiceClass()).toString());
return sb.toString();
} }
@Override public String getNetworkID()
{
return mMessage.getHex(NETWORK_ID, 5);
}
public String getSystem()
{
return mMessage.getHex(SYSTEM_ID, 3);
}
public int getIdentifier()
{
return mMessage.getInt(IDENTIFIER);
}
public int getChannelNumber()
{
return mMessage.getInt(CHANNEL);
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
mIdentifierUpdate = message;
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getIdentifier(); identifiers[0] = getIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getDownlinkFrequency(getChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getUplinkFrequency(getChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,131 +1,150 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.ldu.LDU1Message; import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class NetworkStatusBroadcastExplicit extends LDU1Message public class NetworkStatusBroadcastExplicit extends LDU1Message implements IdentifierReceiver
implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] NETWORK_ID = {364, 365, 366, 367, 372, 373, 374, 375, 376, 377, 382, 383, 384, 385, 386,
LoggerFactory.getLogger( NetworkStatusBroadcastExplicit.class ); 387, 536, 537, 538, 539};
public static final int[] NETWORK_ID = { 364,365,366,367,372,373,374,375, public static final int[] SYSTEM_ID = {540, 541, 546, 547, 548, 549, 550, 551, 556, 557, 558, 559};
376,377,382,383,384,385,386,387,536,537,538,539 }; public static final int[] TRANSMIT_IDENTIFIER = {560, 561, 566, 567};
public static final int[] SYSTEM_ID = { 540,541,546,547,548,549,550,551,556, public static final int[] TRANSMIT_CHANNEL = {568, 569, 570, 571, 720, 721, 722, 723, 724, 725, 730, 731};
557,558,559 }; public static final int[] RECEIVE_IDENTIFIER = {732, 733, 734, 735};
public static final int[] TRANSMIT_IDENTIFIER = { 560,561,566,567 }; public static final int[] RECEIVE_CHANNEL = {740, 741, 742, 743, 744, 745, 750, 751, 752, 753, 754, 755};
public static final int[] TRANSMIT_CHANNEL = { 568,569,570,571,720,721,722,
723,724,725,730,731 }; private IBandIdentifier mTransmitIdentifierUpdate;
public static final int[] RECEIVE_IDENTIFIER = { 732,733,734,735 }; private IBandIdentifier mReceiveIdentifierUpdate;
public static final int[] RECEIVE_CHANNEL = { 740,741,742,743,744,745,750,
751,752,753,754,755 }; public NetworkStatusBroadcastExplicit(LDU1Message message)
{
private IBandIdentifier mTransmitIdentifierUpdate; super(message);
private IBandIdentifier mReceiveIdentifierUpdate; }
public NetworkStatusBroadcastExplicit( LDU1Message message )
{
super( message );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.NETWORK_STATUS_BROADCAST_EXPLICIT.getDescription(); return LinkControlOpcode.NETWORK_STATUS_BROADCAST_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " NETWORK:" + getNetworkID() );
sb.append( " SYS:" + getSystem() );
sb.append( " TRANSMIT:" + getTransmitChannel() );
sb.append( " RECEIVE:" + getReceiveChannel() );
return sb.toString();
}
public String getNetworkID()
{
return mMessage.getHex( NETWORK_ID, 5 );
}
public String getSystem()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitIdentifier() ) StringBuilder sb = new StringBuilder();
{
mTransmitIdentifierUpdate = message; sb.append(getMessageStub());
}
if( identifier == getReceiveIdentifier() ) sb.append(" NETWORK:" + getNetworkID());
{ sb.append(" SYS:" + getSystem());
mReceiveIdentifierUpdate = message; sb.append(" TRANSMIT:" + getTransmitChannel());
} sb.append(" RECEIVE:" + getReceiveChannel());
return sb.toString();
} }
@Override public String getNetworkID()
{
return mMessage.getHex(NETWORK_ID, 5);
}
public String getSystem()
{
return mMessage.getHex(SYSTEM_ID, 3);
}
public int getTransmitIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitIdentifier(); identifiers[0] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier(); identifiers[1] = getReceiveIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitIdentifierUpdate, if(mTransmitIdentifierUpdate != null)
getTransmitChannelNumber() ); {
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveIdentifierUpdate, if(mReceiveIdentifierUpdate != null)
getReceiveChannelNumber() ); {
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -6,125 +24,124 @@ import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; public class RFSSStatusBroadcast extends LDU1Message implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class RFSSStatusBroadcast extends LDU1Message
implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] LRA = {364, 365, 366, 367, 372, 373, 374, 375};
LoggerFactory.getLogger( RFSSStatusBroadcast.class ); public static final int[] SYSTEM_ID = {384, 385, 386, 387, 536, 537, 538, 539, 540, 541, 546, 547};
public static final int[] RFSS_ID = {548, 549, 550, 551, 556, 557, 558, 559};
public static final int[] SITE_ID = {560, 561, 566, 567, 568, 569, 570, 571};
public static final int[] IDENTIFIER = {720, 721, 722, 723};
public static final int[] CHANNEL = {724, 725, 730, 731, 732, 733, 734, 735, 740, 741, 742, 743};
public static final int[] SYSTEM_SERVICE_CLASS = {744, 745, 750, 751, 752, 753, 754, 755};
private IBandIdentifier mIdentifierUpdate;
public RFSSStatusBroadcast(LDU1Message message)
{
super(message);
}
public static final int[] LRA = { 364,365,366,367,372,373,374,375 };
public static final int[] SYSTEM_ID = { 384,385,386,387,536,537,538,539,540,
541,546,547 };
public static final int[] RFSS_ID = { 548,549,550,551,556,557,558,559 };
public static final int[] SITE_ID = { 560,561,566,567,568,569,570,571 };
public static final int[] IDENTIFIER = { 720,721,722,723 };
public static final int[] CHANNEL = { 724,725,730,731,732,733,734,735,740,
741,742,743 };
public static final int[] SYSTEM_SERVICE_CLASS = { 744,745,750,751,752,753,
754,755 };
private IBandIdentifier mIdentifierUpdate;
public RFSSStatusBroadcast( LDU1Message message )
{
super( message );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.RFSS_STATUS_BROADCAST.getDescription(); return LinkControlOpcode.RFSS_STATUS_BROADCAST.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SYS:" + getSystem() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " CHAN:" + getChannelNumber() );
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
sb.append( " " + mMessage.toString() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getSystem()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
mIdentifierUpdate = message; StringBuilder sb = new StringBuilder();
sb.append(getMessageStub());
sb.append(" LRA:" + getLocationRegistrationArea());
sb.append(" SYS:" + getSystem());
sb.append(" SITE:" + getRFSubsystemID() + "-" + getSiteID());
sb.append(" CHAN:" + getChannelNumber());
sb.append(" " + SystemService.toString(getSystemServiceClass()));
sb.append(" " + mMessage.toString());
return sb.toString();
} }
@Override public String getLocationRegistrationArea()
{
return mMessage.getHex(LRA, 2);
}
public String getSystem()
{
return mMessage.getHex(SYSTEM_ID, 3);
}
public String getRFSubsystemID()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getIdentifier()
{
return mMessage.getInt(IDENTIFIER);
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getChannelNumber()
{
return mMessage.getInt(CHANNEL);
}
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
mIdentifierUpdate = message;
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getIdentifier(); identifiers[0] = getIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getDownlinkFrequency(getChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getUplinkFrequency(getChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -5,146 +23,148 @@ import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.ldu.LDU1Message; import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class RFSSStatusBroadcastExplicit extends LDU1Message public class RFSSStatusBroadcastExplicit extends LDU1Message implements IdentifierReceiver
implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] LRA = {364, 365, 366, 367, 372, 373, 374, 375};
LoggerFactory.getLogger( RFSSStatusBroadcastExplicit.class ); public static final int[] RECEIVE_IDENTIFIER = {376, 377, 382, 383};
public static final int[] RECEIVE_CHANNEL = {384, 385, 386, 387, 536, 537, 538, 539, 540, 541, 546, 547};
public static final int[] RFSS_ID = {548, 549, 550, 551, 556, 557, 558, 559};
public static final int[] SITE_ID = {560, 561, 566, 567, 568, 569, 570, 571};
public static final int[] TRANSMIT_IDENTIFIER = {720, 721, 722, 723};
public static final int[] TRANSMIT_CHANNEL = {724, 725, 730, 731, 732, 733, 734, 735, 740, 741, 742, 743};
public static final int[] SYSTEM_SERVICE_CLASS = {744, 745, 750, 751, 752, 753, 754, 755};
public static final int[] LRA = { 364,365,366,367,372,373,374,375 }; private IBandIdentifier mTransmitIdentifierUpdate;
public static final int[] RECEIVE_IDENTIFIER = { 376,377,382,383 }; private IBandIdentifier mReceiveIdentifierUpdate;
public static final int[] RECEIVE_CHANNEL = { 384,385,386,387,536,537,538,
539,540,541,546,547 }; public RFSSStatusBroadcastExplicit(LDU1Message source)
public static final int[] RFSS_ID = { 548,549,550,551,556,557,558,559 }; {
public static final int[] SITE_ID = { 560,561,566,567,568,569,570,571 }; super(source);
public static final int[] TRANSMIT_IDENTIFIER = { 720,721,722,723 }; }
public static final int[] TRANSMIT_CHANNEL = { 724,725,730,731,732,733,734,
735,740,741,742,743 };
public static final int[] SYSTEM_SERVICE_CLASS = { 744,745,750,751,752,753,754,755 };
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public RFSSStatusBroadcastExplicit( LDU1Message source )
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.RFSS_STATUS_BROADCAST_EXPLICIT.getDescription(); return LinkControlOpcode.RFSS_STATUS_BROADCAST_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " TRANSMIT:" + getTransmitChannelNumber() );
sb.append( " RECEIVE:" + getReceiveChannelNumber() );
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
sb.append( " " + mMessage.toString() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitIdentifier() ) StringBuilder sb = new StringBuilder();
{
mTransmitIdentifierUpdate = message; sb.append(getMessageStub());
}
sb.append(" LRA:" + getLocationRegistrationArea());
if( identifier == getReceiveIdentifier() )
{ sb.append(" SITE:" + getRFSubsystemID() + "-" + getSiteID());
mReceiveIdentifierUpdate = message;
} sb.append(" TRANSMIT:" + getTransmitChannelNumber());
sb.append(" RECEIVE:" + getReceiveChannelNumber());
sb.append(" " + SystemService.toString(getSystemServiceClass()));
sb.append(" " + mMessage.toString());
return sb.toString();
} }
@Override public String getLocationRegistrationArea()
{
return mMessage.getHex(LRA, 2);
}
public String getRFSubsystemID()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getTransmitIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public int getReceiveIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitIdentifier(); identifiers[0] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier(); identifiers[1] = getReceiveIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() ); if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() ); if(mReceiveIdentifierUpdate != null)
{
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -6,151 +24,162 @@ import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; public class SecondaryControlChannelBroadcast extends LDU1Message implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class SecondaryControlChannelBroadcast extends LDU1Message
implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] RFSS_ID = {364, 365, 366, 367, 372, 373, 374, 375};
LoggerFactory.getLogger( SecondaryControlChannelBroadcast.class ); public static final int[] SITE_ID = {376, 377, 382, 383, 384, 385, 386, 387};
public static final int[] IDENTIFIER_A = {536, 537, 538, 539};
public static final int[] CHANNEL_A = {540, 541, 546, 547, 548, 549, 550, 551, 556, 557, 558, 559};
public static final int[] SYSTEM_SERVICE_CLASS_A = {560, 561, 566, 567, 568, 569, 570, 571};
public static final int[] IDENTIFIER_B = {720, 721, 722, 723};
public static final int[] CHANNEL_B = {724, 725, 730, 731, 732, 733, 734, 735, 740, 741, 742, 743};
public static final int[] SYSTEM_SERVICE_CLASS_B = {744, 745, 750, 751, 752, 753, 754, 755};
public static final int[] RFSS_ID = { 364,365,366,367,372,373,374,375 }; private IBandIdentifier mIdentifierProviderA;
public static final int[] SITE_ID = { 376,377,382,383,384,385,386,387 }; private IBandIdentifier mIdentifierProviderB;
public static final int[] IDENTIFIER_A = { 536,537,538,539 };
public static final int[] CHANNEL_A = { 540,541,546,547,548,549,550,551, public SecondaryControlChannelBroadcast(LDU1Message message)
556,557,558,559 }; {
public static final int[] SYSTEM_SERVICE_CLASS_A = { 560,561,566,567,568,569,570,571 }; super(message);
public static final int[] IDENTIFIER_B = { 720,721,722,723 }; }
public static final int[] CHANNEL_B = { 724,725,730,731,732,733,734,735,740,
741,742,743 };
public static final int[] SYSTEM_SERVICE_CLASS_B = { 744,745,750,751,752,753,754,755 };
private IBandIdentifier mIdentifierProviderA;
private IBandIdentifier mIdentifierProviderB;
public SecondaryControlChannelBroadcast( LDU1Message message )
{
super( message );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST.getDescription(); return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " CHAN A:" + getChannelA() );
sb.append( " " + SystemService.toString( getSystemServiceClassA() ) );
sb.append( " CHAN B:" + getChannelB() );
sb.append( " " + SystemService.toString( getSystemServiceClassB() ) );
return sb.toString();
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifierA()
{
return mMessage.getInt( IDENTIFIER_A );
}
public int getChannelA()
{
return mMessage.getInt( CHANNEL_A );
}
public String getChannelNumberA()
{
return getIdentifierA() + "-" + getChannelA();
}
public int getIdentifierB()
{
return mMessage.getInt( IDENTIFIER_B );
}
public int getChannelB()
{
return mMessage.getInt( CHANNEL_B );
}
public String getChannelNumberB()
{
return getIdentifierB() + "-" + getChannelB();
}
public int getSystemServiceClassA()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS_A );
}
public int getSystemServiceClassB()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS_B );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getIdentifierA() ) StringBuilder sb = new StringBuilder();
{
mIdentifierProviderA = message; sb.append(getMessageStub());
}
if( identifier == getIdentifierB() ) sb.append(" SITE:" + getRFSubsystemID() + "-" + getSiteID());
{
mIdentifierProviderB = message; sb.append(" CHAN A:" + getChannelA());
}
sb.append(" " + SystemService.toString(getSystemServiceClassA()));
sb.append(" CHAN B:" + getChannelB());
sb.append(" " + SystemService.toString(getSystemServiceClassB()));
return sb.toString();
} }
@Override public String getRFSubsystemID()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getIdentifierA()
{
return mMessage.getInt(IDENTIFIER_A);
}
public int getChannelA()
{
return mMessage.getInt(CHANNEL_A);
}
public String getChannelNumberA()
{
return getIdentifierA() + "-" + getChannelA();
}
public int getIdentifierB()
{
return mMessage.getInt(IDENTIFIER_B);
}
public int getChannelB()
{
return mMessage.getInt(CHANNEL_B);
}
public String getChannelNumberB()
{
return getIdentifierB() + "-" + getChannelB();
}
public int getSystemServiceClassA()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS_A);
}
public int getSystemServiceClassB()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS_B);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getIdentifierA())
{
mIdentifierProviderA = message;
}
if(identifier == getIdentifierB())
{
mIdentifierProviderB = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getIdentifierA(); identifiers[0] = getIdentifierA();
identifiers[ 1 ] = getIdentifierB(); identifiers[1] = getIdentifierB();
return identifiers; return identifiers;
} }
public long getDownlinkFrequencyA() public long getDownlinkFrequencyA()
{ {
return calculateDownlink( mIdentifierProviderA, getChannelA() ); if(mIdentifierProviderA != null)
{
return mIdentifierProviderA.getDownlinkFrequency(getChannelA());
}
return 0;
} }
public long getUplinkFrequencyA() public long getUplinkFrequencyA()
{ {
return calculateUplink( mIdentifierProviderA, getChannelA() ); if(mIdentifierProviderA != null)
{
return mIdentifierProviderA.getUplinkFrequency(getChannelA());
}
return 0;
} }
public long getDownlinkFrequencyB() public long getDownlinkFrequencyB()
{ {
return calculateDownlink( mIdentifierProviderB, getChannelB() ); if(mIdentifierProviderB != null)
{
return mIdentifierProviderB.getDownlinkFrequency(getChannelB());
}
return 0;
} }
public long getUplinkFrequencyB() public long getUplinkFrequencyB()
{ {
return calculateUplink( mIdentifierProviderB, getChannelB() ); if(mIdentifierProviderB != null)
{
return mIdentifierProviderB.getUplinkFrequency(getChannelB());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.ldu.lc; package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -6,136 +24,134 @@ import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; public class SecondaryControlChannelBroadcastExplicit extends LDU1Message implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class SecondaryControlChannelBroadcastExplicit
extends LDU1Message implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] RFSS_ID = {364, 365, 366, 367, 372, 373, 374, 375};
LoggerFactory.getLogger( SecondaryControlChannelBroadcastExplicit.class ); public static final int[] SITE_ID = {376, 377, 382, 383, 384, 385, 386, 387};
public static final int[] TRANSMIT_IDENTIFIER = {536, 537, 538, 539};
public static final int[] TRANSMIT_CHANNEL = {540, 541, 546, 547, 548, 549, 550, 551, 556, 557, 558, 559};
public static final int[] RECEIVE_IDENTIFIER = {560, 561, 566, 567};
public static final int[] RECEIVE_CHANNEL = {568, 569, 570, 571, 720, 721, 722, 723, 724, 725, 730, 731};
public static final int[] SYSTEM_SERVICE_CLASS = {732, 733, 734, 735, 740, 741, 742, 743};
private IBandIdentifier mTransmitIdentifierProvider;
private IBandIdentifier mReceiveIdentifierProvider;
public SecondaryControlChannelBroadcastExplicit(LDU1Message message)
{
super(message);
}
public static final int[] RFSS_ID = { 364,365,366,367,372,373,374,375 };
public static final int[] SITE_ID = { 376,377,382,383,384,385,386,387 };
public static final int[] TRANSMIT_IDENTIFIER = { 536,537,538,539 };
public static final int[] TRANSMIT_CHANNEL = { 540,541,546,547,548,549,550,
551,556,557,558,559 };
public static final int[] RECEIVE_IDENTIFIER = { 560,561,566,567 };
public static final int[] RECEIVE_CHANNEL = { 568,569,570,571,720,721,722,
723,724,725,730,731 };
public static final int[] SYSTEM_SERVICE_CLASS = { 732,733,734,735,740,741,
742,743 };
private IBandIdentifier mTransmitIdentifierProvider;
private IBandIdentifier mReceiveIdentifierProvider;
public SecondaryControlChannelBroadcastExplicit( LDU1Message message )
{
super( message );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT.getDescription(); return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " TRANSMIT:" + getTransmitChannel() );
sb.append( " RECEIVE:" + getReceiveChannel() );
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
return sb.toString();
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitIdentifier() ) StringBuilder sb = new StringBuilder();
{
mTransmitIdentifierProvider = message; sb.append(getMessageStub());
}
if( identifier == getReceiveIdentifier() ) sb.append(" SITE:" + getRFSubsystemID() + "-" + getSiteID());
{
mReceiveIdentifierProvider = message; sb.append(" TRANSMIT:" + getTransmitChannel());
}
sb.append(" RECEIVE:" + getReceiveChannel());
sb.append(" " + SystemService.toString(getSystemServiceClass()));
return sb.toString();
} }
@Override public String getRFSubsystemID()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getTransmitIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitIdentifier())
{
mTransmitIdentifierProvider = message;
}
if(identifier == getReceiveIdentifier())
{
mReceiveIdentifierProvider = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitIdentifier(); identifiers[0] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier(); identifiers[1] = getReceiveIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitIdentifierProvider, if(mTransmitIdentifierProvider != null)
getTransmitChannelNumber() ); {
return mTransmitIdentifierProvider.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveIdentifierProvider, if(mReceiveIdentifierProvider != null)
getReceiveChannelNumber() ); {
return mReceiveIdentifierProvider.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,199 +1,220 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.pdu; package module.decode.p25.message.pdu;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID;
import alias.AliasList; import alias.AliasList;
import bits.BinaryMessage; import bits.BinaryMessage;
import edac.CRCP25; import edac.CRCP25;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID;
public abstract class UnitToUnitChannelGrantExtended extends PDUMessage public abstract class UnitToUnitChannelGrantExtended extends PDUMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
/* Service Options */ /* Service Options */
public static final int EMERGENCY_FLAG = 128; public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129; public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130; public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131; public static final int SESSION_MODE = 131;
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97, public static final int[] SOURCE_ADDRESS = {88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 }; 105, 106, 107, 108, 109, 110, 111};
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134, public static final int[] SERVICE_OPTIONS = {128, 129, 130, 131, 132, 133, 134, 135};
135 }; public static final int[] SOURCE_WACN = {160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
public static final int[] SOURCE_WACN = { 160,161,162,163,164,165,166,167, 175, 176, 177, 178, 179};
168,169,170,171,172,173,174,175,176,177,178,179 }; public static final int[] SOURCE_SYSTEM_ID = {180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191};
public static final int[] SOURCE_SYSTEM_ID = { 180,181,182,183,184,185,186, public static final int[] SOURCE_ID = {192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
187,188,189,190,191 }; 207, 208, 209, 210, 211, 212, 213, 214, 215};
public static final int[] SOURCE_ID = { 192,193,194,195,196,197,198,199,200, public static final int[] TARGET_ADDRESS = {216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
201,202,203,204,205,206,207,208,209,210,211,212,213,214,215 }; 230, 231, 232, 233, 234, 235, 236, 237, 238, 239};
public static final int[] TARGET_ADDRESS = { 216,217,218,219,220,221,222, public static final int[] TRANSMIT_IDENTIFIER = {240, 241, 242, 243};
223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 }; public static final int[] TRANSMIT_NUMBER = {244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
public static final int[] TRANSMIT_IDENTIFIER = { 240,241,242,243 }; public static final int[] RECEIVE_IDENTIFIER = {256, 257, 258, 259};
public static final int[] TRANSMIT_NUMBER = { 244,245,246,247,248,249,250, public static final int[] RECEIVE_NUMBER = {260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271};
251,252,253,254,255 }; public static final int[] MULTIPLE_BLOCK_CRC = {320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
public static final int[] RECEIVE_IDENTIFIER = { 256,257,258,259 }; 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351};
public static final int[] RECEIVE_NUMBER = { 260,261,262,263,264,265,266,
267,268,269,270,271 }; private IBandIdentifier mTransmitIdentifierUpdate;
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325, private IBandIdentifier mReceiveIdentifierUpdate;
326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,
343,344,345,346,347,348,349,350,351 }; public UnitToUnitChannelGrantExtended(BinaryMessage message, DataUnitID duid, AliasList aliasList)
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public UnitToUnitChannelGrantExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
/* Header block is already error detected/corrected - perform error /* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */ * detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU2( mMessage ); mMessage = CRCP25.correctPDU2(mMessage);
mCRC[ 1 ] = mMessage.getCRC(); mCRC[1] = mMessage.getCRC();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() ) sb.append(getMessageStub());
if(isEmergency())
{ {
sb.append( " EMERGENCY" ); sb.append(" EMERGENCY");
} }
sb.append( " FROM ADDR:" );
sb.append( getSourceAddress() );
sb.append( " ID:" );
sb.append( getSourceID() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " WACN:" );
sb.append( getSourceWACN() );
sb.append( " SYS:" );
sb.append( getSourceSystemID() );
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() ); sb.append(" FROM ADDR:");
sb.append( " " + getDownlinkFrequency() ); sb.append(getSourceAddress());
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() ); sb.append(" ID:");
sb.append( " " + getUplinkFrequency() ); sb.append(getSourceID());
sb.append(" TO:");
sb.append(getTargetAddress());
sb.append(" WACN:");
sb.append(getSourceWACN());
sb.append(" SYS:");
sb.append(getSourceSystemID());
sb.append(" CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber());
sb.append(" " + getDownlinkFrequency());
sb.append(" CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber());
sb.append(" " + getUplinkFrequency());
return sb.toString(); return sb.toString();
} }
public boolean isEmergency() public boolean isEmergency()
{ {
return mMessage.get( EMERGENCY_FLAG ); return mMessage.get(EMERGENCY_FLAG);
} }
public boolean isEncrypted() public boolean isEncrypted()
{ {
return mMessage.get( ENCRYPTED_CHANNEL_FLAG ); return mMessage.get(ENCRYPTED_CHANNEL_FLAG);
} }
public DuplexMode getDuplexMode() public DuplexMode getDuplexMode()
{ {
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF; return mMessage.get(DUPLEX_MODE) ? DuplexMode.FULL : DuplexMode.HALF;
} }
public SessionMode getSessionMode() public SessionMode getSessionMode()
{ {
return mMessage.get( SESSION_MODE ) ? return mMessage.get(SESSION_MODE) ?
SessionMode.CIRCUIT : SessionMode.PACKET; SessionMode.CIRCUIT : SessionMode.PACKET;
} }
public String getSourceAddress() public String getSourceAddress()
{ {
return mMessage.getHex( SOURCE_ADDRESS, 6 ); return mMessage.getHex(SOURCE_ADDRESS, 6);
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
public String getSourceWACN()
{
return mMessage.getHex( SOURCE_WACN, 5 );
}
public String getSourceSystemID()
{
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
} }
@Override public String getSourceID()
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitChannelIdentifier() ) return mMessage.getHex(SOURCE_ID, 6);
{ }
mTransmitIdentifierUpdate = message;
} public String getSourceWACN()
{
if( identifier == getReceiveChannelIdentifier() ) return mMessage.getHex(SOURCE_WACN, 5);
{ }
mReceiveIdentifierUpdate = message;
} public String getSourceSystemID()
{
return mMessage.getHex(SOURCE_SYSTEM_ID, 3);
}
public String getTargetAddress()
{
return mMessage.getHex(TARGET_ADDRESS, 6);
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_NUMBER);
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_NUMBER);
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
}
public long getUplinkFrequency()
{
if(mReceiveIdentifierUpdate != null)
{
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitChannelIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveChannelIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[2];
idens[0] = getTransmitChannelIdentifier();
idens[1] = getReceiveChannelIdentifier();
return idens;
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitChannelIdentifier();
idens[ 1 ] = getReceiveChannelIdentifier();
return idens;
}
} }

View File

@@ -1,5 +1,26 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.pdu.osp.control; package module.decode.p25.message.pdu.osp.control;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
import module.decode.p25.message.IAdjacentSite; import module.decode.p25.message.IAdjacentSite;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
@@ -7,43 +28,32 @@ import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class AdjacentStatusBroadcastExtended extends PDUMessage public class AdjacentStatusBroadcastExtended extends PDUMessage implements IdentifierReceiver, IAdjacentSite
implements IdentifierReceiver, IAdjacentSite
{ {
public static final int[] LRA = { 88,89,90,91,92,93,94,95 }; public static final int[] LRA = {88, 89, 90, 91, 92, 93, 94, 95};
public static final int[] SYSTEM_ID = { 100,101,102,103,104,105,106,107,108, public static final int[] SYSTEM_ID = {100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111};
109,110,111 }; public static final int[] RF_SUBSYSTEM_ID = {128, 129, 130, 131, 132, 133, 134, 135};
public static final int[] RF_SUBSYSTEM_ID = { 128,129,130,131,132,133,134, public static final int[] SITE_ID = {136, 137, 138, 139, 140, 141, 142, 143};
135 }; public static final int[] TRANSMIT_IDENTIFIER = {160, 161, 162, 163};
public static final int[] SITE_ID = { 136,137,138,139,140,141,142,143 }; public static final int[] TRANSMIT_CHANNEL = {164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175};
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 }; public static final int[] RECEIVE_IDENTIFIER = {176, 177, 178, 179};
public static final int[] TRANSMIT_CHANNEL = { 164,165,166,167,168,169,170, public static final int[] RECEIVE_CHANNEL = {180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191};
171,172,173,174,175 }; public static final int[] SYSTEM_SERVICE_CLASS = {192, 193, 194, 195, 196, 197, 198, 199};
public static final int[] RECEIVE_IDENTIFIER = { 176,177,178,179 }; public static final int[] MULTIPLE_BLOCK_CRC = {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
public static final int[] RECEIVE_CHANNEL = { 180,181,182,183,184,185,186, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
187,188,189,190,191 };
public static final int[] SYSTEM_SERVICE_CLASS = { 192,193,194,195,196,197, private IBandIdentifier mTransmitIdentifierProvider;
198,199 }; private IBandIdentifier mReceiveIdentifierProvider;
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247, public AdjacentStatusBroadcastExtended(BinaryMessage message, DataUnitID duid, AliasList aliasList)
248,249,250,251,252,253,254,255 };
private IBandIdentifier mTransmitIdentifierProvider;
private IBandIdentifier mReceiveIdentifierProvider;
public AdjacentStatusBroadcastExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
/* Header block is already error detected/corrected - perform error /* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */ * detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage ); mMessage = CRCP25.correctPDU1(mMessage);
mCRC[ 1 ] = mMessage.getCRC(); mCRC[1] = mMessage.getCRC();
} }
@Override @Override
@@ -51,138 +61,148 @@ public class AdjacentStatusBroadcastExtended extends PDUMessage
{ {
return Opcode.ADJACENT_STATUS_BROADCAST.getDescription(); return Opcode.ADJACENT_STATUS_BROADCAST.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLRA() ); sb.append(getMessageStub());
sb.append( " SYS:" + getSystemID() );
sb.append( " RFSS:" + getRFSS() );
sb.append( " SITE:" + getSiteID() );
sb.append( " CTRL CHAN:" + getTransmitIdentifier() + "-" + getTransmitChannel() ); sb.append(" LRA:" + getLRA());
sb.append( " DN:" + getDownlinkFrequency() ); sb.append(" SYS:" + getSystemID());
sb.append( " " + getReceiveIdentifier() + "-" + getReceiveChannel() ); sb.append(" RFSS:" + getRFSS());
sb.append(" SITE:" + getSiteID());
sb.append(" CTRL CHAN:" + getTransmitIdentifier() + "-" + getTransmitChannel());
sb.append(" DN:" + getDownlinkFrequency());
sb.append(" " + getReceiveIdentifier() + "-" + getReceiveChannel());
sb.append(" UP:" + getUplinkFrequency());
sb.append(" SYS SVC CLASS:" + getSystemServiceClass());
sb.append( " UP:" + getUplinkFrequency() );
sb.append( " SYS SVC CLASS:" + getSystemServiceClass() );
return sb.toString(); return sb.toString();
} }
public String getUniqueID() public String getUniqueID()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getSystemID() ); sb.append(getSystemID());
sb.append( ":" ); sb.append(":");
sb.append( getRFSS() ); sb.append(getRFSS());
sb.append( ":" ); sb.append(":");
sb.append( getSiteID() ); sb.append(getSiteID());
return sb.toString(); return sb.toString();
} }
public String getSystemID() public String getSystemID()
{ {
return mMessage.getHex( SYSTEM_ID, 3 ); return mMessage.getHex(SYSTEM_ID, 3);
} }
public String getSiteID() public String getSiteID()
{ {
return mMessage.getHex( SITE_ID, 2 ); return mMessage.getHex(SITE_ID, 2);
} }
public int getTransmitIdentifier() public int getTransmitIdentifier()
{ {
return mMessage.getInt( TRANSMIT_IDENTIFIER ); return mMessage.getInt(TRANSMIT_IDENTIFIER);
} }
public int getTransmitChannel() public int getTransmitChannel()
{ {
return mMessage.getInt( TRANSMIT_CHANNEL ); return mMessage.getInt(TRANSMIT_CHANNEL);
} }
public int getReceiveIdentifier() public int getReceiveIdentifier()
{ {
return mMessage.getInt( RECEIVE_IDENTIFIER ); return mMessage.getInt(RECEIVE_IDENTIFIER);
} }
public int getReceiveChannel() public int getReceiveChannel()
{ {
return mMessage.getInt( RECEIVE_CHANNEL ); return mMessage.getInt(RECEIVE_CHANNEL);
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitIdentifierProvider, getTransmitChannel() ); if(mTransmitIdentifierProvider != null)
{
return mTransmitIdentifierProvider.getDownlinkFrequency(getTransmitChannel());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveIdentifierProvider, getReceiveChannel() ); if(mReceiveIdentifierProvider != null)
{
return mReceiveIdentifierProvider.getUplinkFrequency(getReceiveChannel());
}
return 0;
} }
@Override @Override
public void setIdentifierMessage( int identifier, IBandIdentifier message ) public void setIdentifierMessage(int identifier, IBandIdentifier message)
{ {
if( identifier == getTransmitIdentifier() ) if(identifier == getTransmitIdentifier())
{ {
mTransmitIdentifierProvider = message; mTransmitIdentifierProvider = message;
} }
if( identifier == getReceiveIdentifier() ) if(identifier == getReceiveIdentifier())
{ {
mReceiveIdentifierProvider = message; mReceiveIdentifierProvider = message;
} }
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitIdentifier();
idens[ 1 ] = getReceiveIdentifier();
return idens;
}
@Override public int[] getIdentifiers()
public String getRFSS() {
{ int[] idens = new int[2];
return mMessage.getHex( RF_SUBSYSTEM_ID, 2 );
}
@Override idens[0] = getTransmitIdentifier();
public String getLRA() idens[1] = getReceiveIdentifier();
{
return mMessage.getHex( LRA, 2 );
}
@Override return idens;
public String getSystemServiceClass() }
{
return SystemService.toString( mMessage.getInt( SYSTEM_SERVICE_CLASS ) );
}
@Override @Override
public String getDownlinkChannel() public String getRFSS()
{ {
return getTransmitIdentifier() + "-" + getTransmitChannel(); return mMessage.getHex(RF_SUBSYSTEM_ID, 2);
} }
@Override @Override
public String getUplinkChannel() public String getLRA()
{ {
return getReceiveIdentifier() + "-" + getReceiveChannel(); return mMessage.getHex(LRA, 2);
} }
@Override
public String getSystemServiceClass()
{
return SystemService.toString(mMessage.getInt(SYSTEM_SERVICE_CLASS));
}
@Override
public String getDownlinkChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannel();
}
@Override
public String getUplinkChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannel();
}
} }

View File

@@ -1,5 +1,26 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.pdu.osp.control; package module.decode.p25.message.pdu.osp.control;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage; import module.decode.p25.message.pdu.PDUMessage;
@@ -7,42 +28,32 @@ import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.P25NetworkCallsign; import module.decode.p25.reference.P25NetworkCallsign;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class NetworkStatusBroadcastExtended extends PDUMessage public class NetworkStatusBroadcastExtended extends PDUMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
public static final int[] LRA = { 88,89,90,91,92,93,94,95 }; public static final int[] LRA = {88, 89, 90, 91, 92, 93, 94, 95};
public static final int[] SYSTEM_ID = { 100,101,102,103,104,105,106,107,108, public static final int[] SYSTEM_ID = {100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111};
109,110,111 }; public static final int[] WACN = {160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
public static final int[] WACN = { 160,161,162,163,164,165,166,167,168,169, 176, 177, 178, 179};
170,171,172,173,174,175,176,177,178,179 }; public static final int[] TRANSMIT_IDENTIFIER = {184, 185, 186, 187};
public static final int[] TRANSMIT_IDENTIFIER = { 184,185,186,187 }; public static final int[] TRANSMIT_CHANNEL = {188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199};
public static final int[] TRANSMIT_CHANNEL = { 188,189,190,191,192,193,194, public static final int[] RECEIVE_IDENTIFIER = {200, 201, 202, 203};
195,196,197,198,199 }; public static final int[] RECEIVE_CHANNEL = {204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215};
public static final int[] RECEIVE_IDENTIFIER = { 200,201,202,203 }; public static final int[] SYSTEM_SERVICE_CLASS = {216, 217, 218, 219, 220, 221, 222, 223};
public static final int[] RECEIVE_CHANNEL = { 204,205,206,207,208,209,210, public static final int[] MULTIPLE_BLOCK_CRC = {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
211,212,213,214,215 }; 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
public static final int[] SYSTEM_SERVICE_CLASS = { 216,217,218,219,220,221,
222,223 }; private IBandIdentifier mTransmitIdentifierUpdate;
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229, private IBandIdentifier mReceiveIdentifierUpdate;
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255 }; public NetworkStatusBroadcastExtended(BinaryMessage message, DataUnitID duid, AliasList aliasList)
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public NetworkStatusBroadcastExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
/* Header block is already error detected/corrected - perform error /* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */ * detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage ); mMessage = CRCP25.correctPDU1(mMessage);
mCRC[ 1 ] = mMessage.getCRC(); mCRC[1] = mMessage.getCRC();
} }
@Override @Override
@@ -50,111 +61,121 @@ public class NetworkStatusBroadcastExtended extends PDUMessage
{ {
return Opcode.NETWORK_STATUS_BROADCAST.getDescription(); return Opcode.NETWORK_STATUS_BROADCAST.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() ); sb.append(getMessageStub());
sb.append( " WACN:" + getWACN() ); sb.append(" LRA:" + getLocationRegistrationArea());
sb.append( " SYS:" + getSystemID() ); sb.append(" WACN:" + getWACN());
sb.append( " CTRL CHAN:" + getReceiveIdentifier() + "-" + getReceiveChannel() ); sb.append(" SYS:" + getSystemID());
sb.append( " DN:" + getDownlinkFrequency() ); sb.append(" CTRL CHAN:" + getReceiveIdentifier() + "-" + getReceiveChannel());
sb.append( " " + getTransmitIdentifier() + "-" + getTransmitChannel() ); sb.append(" DN:" + getDownlinkFrequency());
sb.append( " UP:" + getUplinkFrequency() ); sb.append(" " + getTransmitIdentifier() + "-" + getTransmitChannel());
sb.append( " SYS SVC CLASS:" + sb.append(" UP:" + getUplinkFrequency());
SystemService.toString( getSystemServiceClass() ) );
sb.append(" SYS SVC CLASS:" +
SystemService.toString(getSystemServiceClass()));
return sb.toString(); return sb.toString();
} }
public String getLocationRegistrationArea() public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getNetworkCallsign()
{
return P25NetworkCallsign.getCallsign( mMessage.getInt( WACN ),
mMessage.getInt( SYSTEM_ID ) );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannel()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannel()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public int getSystemServiceClass()
{ {
return mMessage.getInt( SYSTEM_SERVICE_CLASS ); return mMessage.getHex(LRA, 2);
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannel() );
} }
@Override public String getSystemID()
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitIdentifier() ) return mMessage.getHex(SYSTEM_ID, 3);
{ }
mTransmitIdentifierUpdate = message;
} public String getWACN()
{
if( identifier == getReceiveIdentifier() ) return mMessage.getHex(WACN, 5);
{ }
mReceiveIdentifierUpdate = message;
} public String getNetworkCallsign()
{
return P25NetworkCallsign.getCallsign(mMessage.getInt(WACN),
mMessage.getInt(SYSTEM_ID));
}
public int getTransmitIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannel()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public int getReceiveIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannel()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
public long getDownlinkFrequency()
{
if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannel());
}
return 0;
}
public long getUplinkFrequency()
{
if(mReceiveIdentifierUpdate != null)
{
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannel());
}
return 0;
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[2];
idens[0] = getTransmitIdentifier();
idens[1] = getReceiveIdentifier();
return idens;
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitIdentifier();
idens[ 1 ] = getReceiveIdentifier();
return idens;
}
} }

View File

@@ -1,48 +1,59 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.pdu.osp.control; package module.decode.p25.message.pdu.osp.control;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage; import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class RFSSStatusBroadcastExtended extends PDUMessage public class RFSSStatusBroadcastExtended extends PDUMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
public static final int[] LRA = { 88,89,90,91,92,93,94,95 }; public static final int[] LRA = {88, 89, 90, 91, 92, 93, 94, 95};
public static final int ACTIVE_NETWORK_CONNECTION_INDICATOR = 99; public static final int ACTIVE_NETWORK_CONNECTION_INDICATOR = 99;
public static final int[] SYSTEM_ID = { 100,101,102,103,104,105,106,107,108, public static final int[] SYSTEM_ID = {100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111};
109,110,111 }; public static final int[] RFSS_ID = {160, 161, 162, 163, 164, 165, 166, 167};
public static final int[] RFSS_ID = { 160,161,162,163,164,165,166,167 }; public static final int[] SITE_ID = {168, 169, 170, 171, 172, 173, 174, 175};
public static final int[] SITE_ID = { 168,169,170,171,172,173,174,175 }; public static final int[] TRANSMIT_IDENTIFIER = {184, 185, 186, 187};
public static final int[] TRANSMIT_IDENTIFIER = { 184,185,186,187 }; public static final int[] TRANSMIT_CHANNEL = {188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199};
public static final int[] TRANSMIT_CHANNEL = { 188,189,190,191,192,193,194, public static final int[] RECEIVE_IDENTIFIER = {200, 201, 202, 203};
195,196,197,198,199 }; public static final int[] RECEIVE_CHANNEL = {204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215};
public static final int[] RECEIVE_IDENTIFIER = { 200,201,202,203 }; public static final int[] SYSTEM_SERVICE_CLASS = {216, 217, 218, 219, 220, 221, 222, 223};
public static final int[] RECEIVE_CHANNEL = { 204,205,206,207,208,209,210, public static final int[] MULTIPLE_BLOCK_CRC = {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
211,212,213,214,215 }; 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
public static final int[] SYSTEM_SERVICE_CLASS = { 216,217,218,219,220,221,
222,223 }; private IBandIdentifier mTransmitIdentifierUpdate;
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229, private IBandIdentifier mReceiveIdentifierUpdate;
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255 }; public RFSSStatusBroadcastExtended(BinaryMessage message, DataUnitID duid, AliasList aliasList)
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public RFSSStatusBroadcastExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
/* Header block is already error detected/corrected - perform error /* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */ * detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage ); mMessage = CRCP25.correctPDU1(mMessage);
mCRC[ 1 ] = mMessage.getCRC(); mCRC[1] = mMessage.getCRC();
} }
@Override @Override
@@ -50,115 +61,125 @@ public class RFSSStatusBroadcastExtended extends PDUMessage
{ {
return Opcode.NETWORK_STATUS_BROADCAST.getDescription(); return Opcode.NETWORK_STATUS_BROADCAST.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() ); sb.append(getMessageStub());
sb.append( " SYS:" + getSystemID() ); sb.append(" LRA:" + getLocationRegistrationArea());
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() ); sb.append(" SYS:" + getSystemID());
sb.append( " CTRL CHAN:" + getReceiveIdentifier() + "-" + getReceiveChannel() ); sb.append(" SITE:" + getRFSubsystemID() + "-" + getSiteID());
sb.append( " DN:" + getDownlinkFrequency() ); sb.append(" CTRL CHAN:" + getReceiveIdentifier() + "-" + getReceiveChannel());
sb.append( " " + getTransmitIdentifier() + "-" + getTransmitChannel() ); sb.append(" DN:" + getDownlinkFrequency());
sb.append( " UP:" + getUplinkFrequency() ); sb.append(" " + getTransmitIdentifier() + "-" + getTransmitChannel());
sb.append( " SYS SVC CLASS:" + sb.append(" UP:" + getUplinkFrequency());
SystemService.toString( getSystemServiceClass() ) );
sb.append(" SYS SVC CLASS:" +
SystemService.toString(getSystemServiceClass()));
return sb.toString(); return sb.toString();
} }
public String getLocationRegistrationArea() public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public boolean hasActiveNetworkConnection()
{
return mMessage.get( ACTIVE_NETWORK_CONNECTION_INDICATOR );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannel()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannel()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public int getSystemServiceClass()
{ {
return mMessage.getInt( SYSTEM_SERVICE_CLASS ); return mMessage.getHex(LRA, 2);
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannel() );
} }
@Override public boolean hasActiveNetworkConnection()
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitIdentifier() ) return mMessage.get(ACTIVE_NETWORK_CONNECTION_INDICATOR);
{ }
mTransmitIdentifierUpdate = message;
} public String getSystemID()
{
if( identifier == getReceiveIdentifier() ) return mMessage.getHex(SYSTEM_ID, 3);
{ }
mReceiveIdentifierUpdate = message;
} public String getRFSubsystemID()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getTransmitIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannel()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public int getReceiveIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannel()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
public long getDownlinkFrequency()
{
if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannel());
}
return 0;
}
public long getUplinkFrequency()
{
if(mReceiveIdentifierUpdate != null)
{
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannel());
}
return 0;
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[2];
idens[0] = getTransmitIdentifier();
idens[1] = getReceiveIdentifier();
return idens;
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitIdentifier();
idens[ 1 ] = getReceiveIdentifier();
return idens;
}
} }

View File

@@ -1,51 +1,63 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.pdu.osp.data; package module.decode.p25.message.pdu.osp.data;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage; import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class GroupDataChannelGrantExtended extends PDUMessage public class GroupDataChannelGrantExtended extends PDUMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
/* Service Options */ /* Service Options */
public static final int EMERGENCY_FLAG = 128; public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129; public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130; public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131; public static final int SESSION_MODE = 131;
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97, public static final int[] SOURCE_ADDRESS = {88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 }; 104, 105, 106, 107, 108, 109, 110, 111};
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134, public static final int[] SERVICE_OPTIONS = {128, 129, 130, 131, 132, 133, 134, 135};
135 }; public static final int[] TRANSMIT_IDENTIFIER = {160, 161, 162, 163};
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 }; public static final int[] TRANSMIT_NUMBER = {164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175};
public static final int[] TRANSMIT_NUMBER = { 164,165,166,167,168,169,170, public static final int[] RECEIVE_IDENTIFIER = {176, 177, 178, 179};
171,172,173,174,175 }; public static final int[] RECEIVE_NUMBER = {180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191};
public static final int[] RECEIVE_IDENTIFIER = { 176,177,178,179 }; public static final int[] GROUP_ADDRESS = {192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
public static final int[] RECEIVE_NUMBER = { 180,181,182,183,184,185,186, 206, 207};
187,188,189,190,191 }; public static final int[] MULTIPLE_BLOCK_CRC = {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
public static final int[] GROUP_ADDRESS = { 192,193,194,195,196,197,198,199, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
200,201,202,203,204,205,206,207 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229, private IBandIdentifier mTransmitIdentifierUpdate;
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247, private IBandIdentifier mReceiveIdentifierUpdate;
248,249,250,251,252,253,254,255 };
public GroupDataChannelGrantExtended(BinaryMessage message, DataUnitID duid, AliasList aliasList)
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public GroupDataChannelGrantExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
/* Header block is already error detected/corrected - perform error /* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */ * detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage ); mMessage = CRCP25.correctPDU1(mMessage);
mCRC[ 1 ] = mMessage.getCRC(); mCRC[1] = mMessage.getCRC();
} }
@Override @Override
@@ -53,125 +65,135 @@ public class GroupDataChannelGrantExtended extends PDUMessage
{ {
return Opcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT.getDescription(); return Opcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() ) sb.append(getMessageStub());
if(isEmergency())
{ {
sb.append( " EMERGENCY" ); sb.append(" EMERGENCY");
} }
sb.append( " FROM:" ); sb.append(" FROM:");
sb.append( getSourceAddress() ); sb.append(getSourceAddress());
sb.append( " TO:" ); sb.append(" TO:");
sb.append( getGroupAddress() ); sb.append(getGroupAddress());
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() ); sb.append(" CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber());
sb.append( " " + getDownlinkFrequency() ); sb.append(" " + getDownlinkFrequency());
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() ); sb.append(" CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber());
sb.append( " " + getUplinkFrequency() ); sb.append(" " + getUplinkFrequency());
return sb.toString(); return sb.toString();
} }
public boolean isEmergency() public boolean isEmergency()
{ {
return mMessage.get( EMERGENCY_FLAG ); return mMessage.get(EMERGENCY_FLAG);
} }
public boolean isEncrypted() public boolean isEncrypted()
{ {
return mMessage.get( ENCRYPTED_CHANNEL_FLAG ); return mMessage.get(ENCRYPTED_CHANNEL_FLAG);
} }
public DuplexMode getDuplexMode() public DuplexMode getDuplexMode()
{ {
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF; return mMessage.get(DUPLEX_MODE) ? DuplexMode.FULL : DuplexMode.HALF;
} }
public SessionMode getSessionMode() public SessionMode getSessionMode()
{ {
return mMessage.get( SESSION_MODE ) ? return mMessage.get(SESSION_MODE) ?
SessionMode.CIRCUIT : SessionMode.PACKET; SessionMode.CIRCUIT : SessionMode.PACKET;
} }
public String getSourceAddress() public String getSourceAddress()
{ {
return mMessage.getHex( SOURCE_ADDRESS, 6 ); return mMessage.getHex(SOURCE_ADDRESS, 6);
} }
public String getGroupAddress() public String getGroupAddress()
{ {
return mMessage.getHex( GROUP_ADDRESS, 4 ); return mMessage.getHex(GROUP_ADDRESS, 4);
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
} }
@Override public int getTransmitChannelIdentifier()
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitChannelIdentifier() ) return mMessage.getInt(TRANSMIT_IDENTIFIER);
{ }
mTransmitIdentifierUpdate = message;
} public int getTransmitChannelNumber()
{
if( identifier == getReceiveChannelIdentifier() ) return mMessage.getInt(TRANSMIT_NUMBER);
{ }
mReceiveIdentifierUpdate = message;
} public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_NUMBER);
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
}
public long getUplinkFrequency()
{
if(mReceiveIdentifierUpdate != null)
{
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitChannelIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveChannelIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[2];
idens[0] = getTransmitChannelIdentifier();
idens[1] = getReceiveChannelIdentifier();
return idens;
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitChannelIdentifier();
idens[ 1 ] = getReceiveChannelIdentifier();
return idens;
}
} }

View File

@@ -1,51 +1,63 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.pdu.osp.voice; package module.decode.p25.message.pdu.osp.voice;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage; import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class GroupVoiceChannelGrantExplicit extends PDUMessage public class GroupVoiceChannelGrantExplicit extends PDUMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
/* Service Options */ /* Service Options */
public static final int EMERGENCY_FLAG = 128; public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129; public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130; public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131; public static final int SESSION_MODE = 131;
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97, public static final int[] SOURCE_ADDRESS = {88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 }; 105, 106, 107, 108, 109, 110, 111};
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134, public static final int[] SERVICE_OPTIONS = {128, 129, 130, 131, 132, 133, 134, 135};
135 }; public static final int[] TRANSMIT_IDENTIFIER = {176, 177, 178, 179};
public static final int[] TRANSMIT_IDENTIFIER = { 176,177,178,179 }; public static final int[] TRANSMIT_NUMBER = {180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191};
public static final int[] TRANSMIT_NUMBER = { 180,181,182,183,184,185,186, public static final int[] RECEIVE_IDENTIFIER = {192, 193, 194, 195};
187,188,189,190,191 }; public static final int[] RECEIVE_NUMBER = {196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207};
public static final int[] RECEIVE_IDENTIFIER = { 192,193,194,195 }; public static final int[] GROUP_ADDRESS = {208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
public static final int[] RECEIVE_NUMBER = { 196,197,198,199,200,201,202, 222, 223};
203,204,205,206,207 }; public static final int[] MULTIPLE_BLOCK_CRC = {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
public static final int[] GROUP_ADDRESS = { 208,209,210,211,212,213,214,215, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
216,217,218,219,220,221,222,223 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229, private IBandIdentifier mTransmitIdentifierUpdate;
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247, private IBandIdentifier mReceiveIdentifierUpdate;
248,249,250,251,252,253,254,255 };
public GroupVoiceChannelGrantExplicit(BinaryMessage message, DataUnitID duid, AliasList aliasList)
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public GroupVoiceChannelGrantExplicit( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
/* Header block is already error detected/corrected - perform error /* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */ * detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage ); mMessage = CRCP25.correctPDU1(mMessage);
mCRC[ 1 ] = mMessage.getCRC(); mCRC[1] = mMessage.getCRC();
} }
@Override @Override
@@ -53,125 +65,135 @@ public class GroupVoiceChannelGrantExplicit extends PDUMessage
{ {
return Opcode.GROUP_VOICE_CHANNEL_GRANT.getDescription(); return Opcode.GROUP_VOICE_CHANNEL_GRANT.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() ) sb.append(getMessageStub());
if(isEmergency())
{ {
sb.append( " EMERGENCY" ); sb.append(" EMERGENCY");
} }
sb.append( " FROM:" );
sb.append( getSourceAddress() );
sb.append( " GRP:" );
sb.append( getGroupAddress() );
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() ); sb.append(" FROM:");
sb.append( " " + getDownlinkFrequency() ); sb.append(getSourceAddress());
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() ); sb.append(" GRP:");
sb.append( " " + getUplinkFrequency() ); sb.append(getGroupAddress());
sb.append(" CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber());
sb.append(" " + getDownlinkFrequency());
sb.append(" CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber());
sb.append(" " + getUplinkFrequency());
return sb.toString(); return sb.toString();
} }
public boolean isEmergency() public boolean isEmergency()
{ {
return mMessage.get( EMERGENCY_FLAG ); return mMessage.get(EMERGENCY_FLAG);
} }
public boolean isEncrypted() public boolean isEncrypted()
{ {
return mMessage.get( ENCRYPTED_CHANNEL_FLAG ); return mMessage.get(ENCRYPTED_CHANNEL_FLAG);
} }
public DuplexMode getDuplexMode() public DuplexMode getDuplexMode()
{ {
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF; return mMessage.get(DUPLEX_MODE) ? DuplexMode.FULL : DuplexMode.HALF;
} }
public SessionMode getSessionMode() public SessionMode getSessionMode()
{ {
return mMessage.get( SESSION_MODE ) ? return mMessage.get(SESSION_MODE) ?
SessionMode.CIRCUIT : SessionMode.PACKET; SessionMode.CIRCUIT : SessionMode.PACKET;
} }
public String getSourceAddress() public String getSourceAddress()
{ {
return mMessage.getHex( SOURCE_ADDRESS, 6 ); return mMessage.getHex(SOURCE_ADDRESS, 6);
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
} }
@Override public String getGroupAddress()
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitChannelIdentifier() ) return mMessage.getHex(GROUP_ADDRESS, 4);
{ }
mTransmitIdentifierUpdate = message;
} public int getTransmitChannelIdentifier()
{
if( identifier == getReceiveChannelIdentifier() ) return mMessage.getInt(TRANSMIT_IDENTIFIER);
{ }
mReceiveIdentifierUpdate = message;
} public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_NUMBER);
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_NUMBER);
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
}
public long getUplinkFrequency()
{
if(mReceiveIdentifierUpdate != null)
{
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitChannelIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveChannelIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[2];
idens[0] = getTransmitChannelIdentifier();
idens[1] = getReceiveChannelIdentifier();
return idens;
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitChannelIdentifier();
idens[ 1 ] = getReceiveChannelIdentifier();
return idens;
}
} }

View File

@@ -1,53 +1,64 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.pdu.osp.voice; package module.decode.p25.message.pdu.osp.voice;
import java.util.Date; import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage; import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class TelephoneInterconnectChannelGrantExplicit extends PDUMessage import java.util.Date;
implements IdentifierReceiver
public class TelephoneInterconnectChannelGrantExplicit extends PDUMessage implements IdentifierReceiver
{ {
/* Service Options */ /* Service Options */
public static final int EMERGENCY_FLAG = 128; public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129; public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130; public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131; public static final int SESSION_MODE = 131;
public static final int[] ADDRESS = { 88,89,90,91,92,93,94,95,96,97, public static final int[] ADDRESS = {88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 }; 106, 107, 108, 109, 110, 111};
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134, public static final int[] SERVICE_OPTIONS = {128, 129, 130, 131, 132, 133, 134, 135};
135 }; public static final int[] TRANSMIT_IDENTIFIER = {160, 161, 162, 163};
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 }; public static final int[] TRANSMIT_NUMBER = {164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175};
public static final int[] TRANSMIT_NUMBER = { 164,165,166,167,168,169,170, public static final int[] RECEIVE_IDENTIFIER = {176, 177, 178, 179};
171,172,173,174,175 }; public static final int[] RECEIVE_NUMBER = {180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191};
public static final int[] RECEIVE_IDENTIFIER = { 176,177,178,179 }; public static final int[] CALL_TIMER = {192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207};
public static final int[] RECEIVE_NUMBER = { 180,181,182,183,184,185,186, public static final int[] MULTIPLE_BLOCK_CRC = {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
187,188,189,190,191 }; 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
public static final int[] CALL_TIMER = { 192,193,194,195,196,197,198,199,
200,201,202,203,204,205,206,207 }; private IBandIdentifier mTransmitIdentifierUpdate;
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229, private IBandIdentifier mReceiveIdentifierUpdate;
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255 }; public TelephoneInterconnectChannelGrantExplicit(BinaryMessage message, DataUnitID duid, AliasList aliasList)
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public TelephoneInterconnectChannelGrantExplicit( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
/* Header block is already error detected/corrected - perform error /* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */ * detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage ); mMessage = CRCP25.correctPDU1(mMessage);
mCRC[ 1 ] = mMessage.getCRC(); mCRC[1] = mMessage.getCRC();
} }
@Override @Override
@@ -55,57 +66,57 @@ public class TelephoneInterconnectChannelGrantExplicit extends PDUMessage
{ {
return Opcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT.getDescription(); return Opcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() ) sb.append(getMessageStub());
if(isEmergency())
{ {
sb.append( " EMERGENCY" ); sb.append(" EMERGENCY");
} }
sb.append( " ADDR:" ); sb.append(" ADDR:");
sb.append( getAddress() ); sb.append(getAddress());
sb.append( " CALL TIMER:" ); sb.append(" CALL TIMER:");
sb.append( mTimeDurationFormat.format( new Date( getCallTimer() ) ) ); sb.append(mTimeDurationFormat.format(new Date(getCallTimer())));
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() ); sb.append(" CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber());
sb.append( " " + getDownlinkFrequency() ); sb.append(" " + getDownlinkFrequency());
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() ); sb.append(" CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber());
sb.append( " " + getUplinkFrequency() ); sb.append(" " + getUplinkFrequency());
return sb.toString(); return sb.toString();
} }
public boolean isEmergency() public boolean isEmergency()
{ {
return mMessage.get( EMERGENCY_FLAG ); return mMessage.get(EMERGENCY_FLAG);
} }
public boolean isEncrypted() public boolean isEncrypted()
{ {
return mMessage.get( ENCRYPTED_CHANNEL_FLAG ); return mMessage.get(ENCRYPTED_CHANNEL_FLAG);
} }
public DuplexMode getDuplexMode() public DuplexMode getDuplexMode()
{ {
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF; return mMessage.get(DUPLEX_MODE) ? DuplexMode.FULL : DuplexMode.HALF;
} }
public SessionMode getSessionMode() public SessionMode getSessionMode()
{ {
return mMessage.get( SESSION_MODE ) ? return mMessage.get(SESSION_MODE) ?
SessionMode.CIRCUIT : SessionMode.PACKET; SessionMode.CIRCUIT : SessionMode.PACKET;
} }
public String getAddress() public String getAddress()
{ {
return mMessage.getHex( ADDRESS, 6 ); return mMessage.getHex(ADDRESS, 6);
} }
/* /*
@@ -113,72 +124,82 @@ public class TelephoneInterconnectChannelGrantExplicit extends PDUMessage
*/ */
public long getCallTimer() public long getCallTimer()
{ {
int timer = mMessage.getInt( CALL_TIMER ); int timer = mMessage.getInt(CALL_TIMER);
return timer / 100; return timer / 100;
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
} }
@Override public int getTransmitChannelIdentifier()
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitChannelIdentifier() ) return mMessage.getInt(TRANSMIT_IDENTIFIER);
{ }
mTransmitIdentifierUpdate = message;
} public int getTransmitChannelNumber()
{
if( identifier == getReceiveChannelIdentifier() ) return mMessage.getInt(TRANSMIT_NUMBER);
{ }
mReceiveIdentifierUpdate = message;
} public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_NUMBER);
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
}
public long getUplinkFrequency()
{
if(mReceiveIdentifierUpdate != null)
{
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitChannelIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveChannelIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[2];
idens[0] = getTransmitChannelIdentifier();
idens[1] = getReceiveChannelIdentifier();
return idens;
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitChannelIdentifier();
idens[ 1 ] = getReceiveChannelIdentifier();
return idens;
}
} }

View File

@@ -1,57 +1,68 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.pdu.osp.voice; package module.decode.p25.message.pdu.osp.voice;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage; import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class UnitToUnitVoiceChannelGrantUpdateExtended extends PDUMessage public class UnitToUnitVoiceChannelGrantUpdateExtended extends PDUMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
/* Service Options */ /* Service Options */
public static final int EMERGENCY_FLAG = 128; public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129; public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130; public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131; public static final int SESSION_MODE = 131;
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97, public static final int[] SOURCE_ADDRESS = {88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 }; 105, 106, 107, 108, 109, 110, 111};
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134, public static final int[] SERVICE_OPTIONS = {128, 129, 130, 131, 132, 133, 134, 135};
135 }; public static final int[] SOURCE_WACN = {160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
public static final int[] SOURCE_WACN = { 160,161,162,163,164,165,166,167, 175, 176, 177, 178, 179};
168,169,170,171,172,173,174,175,176,177,178,179 }; public static final int[] SOURCE_SYSTEM_ID = {180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191};
public static final int[] SOURCE_SYSTEM_ID = { 180,181,182,183,184,185,186, public static final int[] SOURCE_ID = {192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
187,188,189,190,191 }; 207, 208, 209, 210, 211, 212, 213, 214, 215};
public static final int[] SOURCE_ID = { 192,193,194,195,196,197,198,199,200, public static final int[] TARGET_ADDRESS = {216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
201,202,203,204,205,206,207,208,209,210,211,212,213,214,215 }; 230, 231, 232, 233, 234, 235, 236, 237, 238, 239};
public static final int[] TARGET_ADDRESS = { 216,217,218,219,220,221,222, public static final int[] TRANSMIT_IDENTIFIER = {240, 241, 242, 243};
223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 }; public static final int[] TRANSMIT_NUMBER = {244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
public static final int[] TRANSMIT_IDENTIFIER = { 240,241,242,243 }; public static final int[] RECEIVE_IDENTIFIER = {256, 257, 258, 259};
public static final int[] TRANSMIT_NUMBER = { 244,245,246,247,248,249,250, public static final int[] RECEIVE_NUMBER = {260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271};
251,252,253,254,255 }; public static final int[] MULTIPLE_BLOCK_CRC = {320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
public static final int[] RECEIVE_IDENTIFIER = { 256,257,258,259 }; 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351};
public static final int[] RECEIVE_NUMBER = { 260,261,262,263,264,265,266,
267,268,269,270,271 }; private IBandIdentifier mTransmitIdentifierUpdate;
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325, private IBandIdentifier mReceiveIdentifierUpdate;
326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,
343,344,345,346,347,348,349,350,351 }; public UnitToUnitVoiceChannelGrantUpdateExtended(BinaryMessage message, DataUnitID duid, AliasList aliasList)
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public UnitToUnitVoiceChannelGrantUpdateExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
/* Header block is already error detected/corrected - perform error /* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */ * detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU2( mMessage ); mMessage = CRCP25.correctPDU2(mMessage);
mCRC[ 1 ] = mMessage.getCRC(); mCRC[1] = mMessage.getCRC();
} }
@Override @Override
@@ -59,149 +70,159 @@ public class UnitToUnitVoiceChannelGrantUpdateExtended extends PDUMessage
{ {
return Opcode.UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE.getDescription(); return Opcode.UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() ) sb.append(getMessageStub());
if(isEmergency())
{ {
sb.append( " EMERGENCY" ); sb.append(" EMERGENCY");
} }
sb.append( " FROM ADDR:" );
sb.append( getSourceAddress() );
sb.append( " ID:" );
sb.append( getSourceID() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " WACN:" );
sb.append( getSourceWACN() );
sb.append( " SYS:" );
sb.append( getSourceSystemID() );
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() ); sb.append(" FROM ADDR:");
sb.append( " " + getDownlinkFrequency() ); sb.append(getSourceAddress());
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() ); sb.append(" ID:");
sb.append( " " + getUplinkFrequency() ); sb.append(getSourceID());
sb.append(" TO:");
sb.append(getTargetAddress());
sb.append(" WACN:");
sb.append(getSourceWACN());
sb.append(" SYS:");
sb.append(getSourceSystemID());
sb.append(" CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber());
sb.append(" " + getDownlinkFrequency());
sb.append(" CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber());
sb.append(" " + getUplinkFrequency());
return sb.toString(); return sb.toString();
} }
public boolean isEmergency() public boolean isEmergency()
{ {
return mMessage.get( EMERGENCY_FLAG ); return mMessage.get(EMERGENCY_FLAG);
} }
public boolean isEncrypted() public boolean isEncrypted()
{ {
return mMessage.get( ENCRYPTED_CHANNEL_FLAG ); return mMessage.get(ENCRYPTED_CHANNEL_FLAG);
} }
public DuplexMode getDuplexMode() public DuplexMode getDuplexMode()
{ {
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF; return mMessage.get(DUPLEX_MODE) ? DuplexMode.FULL : DuplexMode.HALF;
} }
public SessionMode getSessionMode() public SessionMode getSessionMode()
{ {
return mMessage.get( SESSION_MODE ) ? return mMessage.get(SESSION_MODE) ?
SessionMode.CIRCUIT : SessionMode.PACKET; SessionMode.CIRCUIT : SessionMode.PACKET;
} }
public String getSourceAddress() public String getSourceAddress()
{ {
return mMessage.getHex( SOURCE_ADDRESS, 6 ); return mMessage.getHex(SOURCE_ADDRESS, 6);
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
public String getSourceWACN()
{
return mMessage.getHex( SOURCE_WACN, 5 );
}
public String getSourceSystemID()
{
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
} }
@Override public String getSourceID()
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitChannelIdentifier() ) return mMessage.getHex(SOURCE_ID, 6);
{ }
mTransmitIdentifierUpdate = message;
} public String getSourceWACN()
{
if( identifier == getReceiveChannelIdentifier() ) return mMessage.getHex(SOURCE_WACN, 5);
{ }
mReceiveIdentifierUpdate = message;
} public String getSourceSystemID()
{
return mMessage.getHex(SOURCE_SYSTEM_ID, 3);
}
public String getTargetAddress()
{
return mMessage.getHex(TARGET_ADDRESS, 6);
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_NUMBER);
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_NUMBER);
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
}
public long getUplinkFrequency()
{
if(mReceiveIdentifierUpdate != null)
{
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitChannelIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveChannelIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[2];
idens[0] = getTransmitChannelIdentifier();
idens[1] = getReceiveChannelIdentifier();
return idens;
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitChannelIdentifier();
idens[ 1 ] = getReceiveChannelIdentifier();
return idens;
}
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IAdjacentSite; import module.decode.p25.message.IAdjacentSite;
@@ -6,141 +24,147 @@ import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
public class AdjacentSiteStatusBroadcast extends TDULinkControlMessage public class AdjacentSiteStatusBroadcast extends TDULinkControlMessage implements IdentifierReceiver, IAdjacentSite
implements IdentifierReceiver, IAdjacentSite
{ {
public static final int[] LRA = { 72,73,74,75,88,89,90,91 }; public static final int[] LRA = {72, 73, 74, 75, 88, 89, 90, 91};
public static final int[] SYSTEM_ID = { 96,97,98,99,112,113,114,115, public static final int[] SYSTEM_ID = {96, 97, 98, 99, 112, 113, 114, 115, 116, 117, 118, 119};
116,117,118,119 }; public static final int[] RFSS_ID = {120, 121, 122, 123, 136, 137, 138, 139};
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,139 }; public static final int[] SITE_ID = {140, 141, 142, 143, 144, 145, 146, 147};
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 }; public static final int[] IDENTIFIER = {160, 161, 162, 163};
public static final int[] IDENTIFIER = { 160,161,162,163 }; public static final int[] CHANNEL = {164, 165, 166, 167, 168, 169, 170, 171, 184, 185, 186, 187};
public static final int[] CHANNEL = { 164,165,166,167,168,169,170, public static final int[] SYSTEM_SERVICE_CLASS = {188, 189, 190, 191, 192, 193, 194, 195};
171,184,185,186,187 };
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193, private IBandIdentifier mIdentifierUpdate;
194,195 };
public AdjacentSiteStatusBroadcast(TDULinkControlMessage source)
private IBandIdentifier mIdentifierUpdate; {
super(source);
public AdjacentSiteStatusBroadcast( TDULinkControlMessage source ) }
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST.getDescription(); return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLRA() );
sb.append( " SYS:" + getSystemID() ); sb.append(getMessageStub());
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() ); sb.append(" LRA:" + getLRA());
sb.append( " CHAN:" + getChannel() ); sb.append(" SYS:" + getSystemID());
sb.append(" SITE:" + getRFSS() + "-" + getSiteID());
sb.append(" CHAN:" + getChannel());
sb.append(" " + getSystemServiceClass());
return sb.toString();
}
sb.append( " " + getSystemServiceClass() );
return sb.toString();
}
public String getUniqueID() public String getUniqueID()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getSystemID() ); sb.append(getSystemID());
sb.append( ":" ); sb.append(":");
sb.append( getRFSS() ); sb.append(getRFSS());
sb.append( ":" ); sb.append(":");
sb.append( getSiteID() ); sb.append(getSiteID());
return sb.toString(); return sb.toString();
} }
public String getLRA()
{
return mMessage.getHex( LRA, 2 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSS()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
@Override
public String getDownlinkChannel()
{
return getChannel();
}
@Override public String getLRA()
public String getUplinkChannel()
{
return getChannel();
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public String getSystemServiceClass()
{
return SystemService.toString( mMessage.getInt( SYSTEM_SERVICE_CLASS ) );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
mIdentifierUpdate = message; return mMessage.getHex(LRA, 2);
} }
@Override public String getSystemID()
{
return mMessage.getHex(SYSTEM_ID, 3);
}
public String getRFSS()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getIdentifier()
{
return mMessage.getInt(IDENTIFIER);
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
@Override
public String getDownlinkChannel()
{
return getChannel();
}
@Override
public String getUplinkChannel()
{
return getChannel();
}
public int getChannelNumber()
{
return mMessage.getInt(CHANNEL);
}
public String getSystemServiceClass()
{
return SystemService.toString(mMessage.getInt(SYSTEM_SERVICE_CLASS));
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
mIdentifierUpdate = message;
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getIdentifier(); identifiers[0] = getIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getDownlinkFrequency(getChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getUplinkFrequency(getChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IAdjacentSite; import module.decode.p25.message.IAdjacentSite;
@@ -5,153 +23,162 @@ import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
public class AdjacentSiteStatusBroadcastExplicit extends TDULinkControlMessage public class AdjacentSiteStatusBroadcastExplicit extends TDULinkControlMessage implements IdentifierReceiver, IAdjacentSite
implements IdentifierReceiver, IAdjacentSite
{ {
public static final int[] LRA = { 72,73,74,75,88,89,90,91 }; public static final int[] LRA = {72, 73, 74, 75, 88, 89, 90, 91};
public static final int[] TRANSMIT_IDENTIFIER = { 92,93,94,95 }; public static final int[] TRANSMIT_IDENTIFIER = {92, 93, 94, 95};
public static final int[] TRANSMIT_CHANNEL = { 96,97,98,99,112,113,114,115, public static final int[] TRANSMIT_CHANNEL = {96, 97, 98, 99, 112, 113, 114, 115,
116,117,118,119 }; 116, 117, 118, 119};
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,139 }; public static final int[] RFSS_ID = {120, 121, 122, 123, 136, 137, 138, 139};
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 }; public static final int[] SITE_ID = {140, 141, 142, 143, 144, 145, 146, 147};
public static final int[] RECEIVE_IDENTIFIER = { 160,161,162,163 }; public static final int[] RECEIVE_IDENTIFIER = {160, 161, 162, 163};
public static final int[] RECEIVE_CHANNEL = { 164,165,166,167,168,169,170, public static final int[] RECEIVE_CHANNEL = {164, 165, 166, 167, 168, 169, 170,
171,184,185,186,187 }; 171, 184, 185, 186, 187};
private IBandIdentifier mTransmitBand; private IBandIdentifier mTransmitBand;
private IBandIdentifier mReceiveBand; private IBandIdentifier mReceiveBand;
public AdjacentSiteStatusBroadcastExplicit(TDULinkControlMessage source)
{
super(source);
}
public AdjacentSiteStatusBroadcastExplicit( TDULinkControlMessage source )
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT.getDescription(); return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append(getMessageStub());
sb.append( " LRA:" + getLRA() ); sb.append(" LRA:" + getLRA());
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() ); sb.append(" SITE:" + getRFSS() + "-" + getSiteID());
sb.append( " DNLINK:" + getDownlinkChannel() ); sb.append(" DNLINK:" + getDownlinkChannel());
sb.append( " UPLINK:" + getUplinkChannel() ); sb.append(" UPLINK:" + getUplinkChannel());
return sb.toString(); return sb.toString();
} }
public String getUniqueID() public String getUniqueID()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getSystemID() ); sb.append(getSystemID());
sb.append( ":" ); sb.append(":");
sb.append( getRFSS() ); sb.append(getRFSS());
sb.append( ":" ); sb.append(":");
sb.append( getSiteID() ); sb.append(getSiteID());
return sb.toString(); return sb.toString();
} }
public String getLRA() public String getLRA()
{ {
return mMessage.getHex( LRA, 2 ); return mMessage.getHex(LRA, 2);
} }
public String getRFSS() public String getRFSS()
{ {
return mMessage.getHex( RFSS_ID, 2 ); return mMessage.getHex(RFSS_ID, 2);
} }
public String getSystemID() public String getSystemID()
{ {
return "***"; return "***";
} }
public String getSiteID() public String getSiteID()
{ {
return mMessage.getHex( SITE_ID, 2 ); return mMessage.getHex(SITE_ID, 2);
} }
@Override @Override
public String getSystemServiceClass() public String getSystemServiceClass()
{ {
return "[]"; return "[]";
} }
public int getTransmitIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannel()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public String getDownlinkChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannel();
}
public int getReceiveIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannel()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public String getUplinkChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannel();
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannel()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getDownlinkChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannel();
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannel()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getUplinkChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannel();
}
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitBand, getTransmitChannel() ); if(mTransmitBand != null)
{
return mTransmitBand.getDownlinkFrequency(getTransmitChannel());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveBand, getReceiveChannel() ); if(mReceiveBand != null)
{
return mReceiveBand.getUplinkFrequency(getReceiveChannel());
}
return 0;
} }
@Override @Override
public void setIdentifierMessage( int identifier, IBandIdentifier message ) public void setIdentifierMessage(int identifier, IBandIdentifier message)
{ {
if( identifier == getTransmitIdentifier() ) if(identifier == getTransmitIdentifier())
{ {
mTransmitBand = message; mTransmitBand = message;
} }
if( identifier == getReceiveIdentifier() )
{
mReceiveBand = message;
}
}
@Override if(identifier == getReceiveIdentifier())
public int[] getIdentifiers() {
{ mReceiveBand = message;
int[] identifiers = new int[ 2 ]; }
}
identifiers[ 0 ] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier(); @Override
public int[] getIdentifiers()
return identifiers; {
} int[] identifiers = new int[2];
identifiers[0] = getTransmitIdentifier();
identifiers[1] = getReceiveIdentifier();
return identifiers;
}
} }

View File

@@ -1,82 +1,117 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
public class ChannelIdentifierUpdate extends TDULinkControlMessage public class ChannelIdentifierUpdate extends TDULinkControlMessage implements IBandIdentifier
implements IBandIdentifier
{ {
public static final int[] IDENTIFIER = { 72,73,74,75 }; public static final int[] IDENTIFIER = {72, 73, 74, 75};
public static final int[] BANDWIDTH = { 88,89,90,91,92,93,94,95,96 }; public static final int[] BANDWIDTH = {88, 89, 90, 91, 92, 93, 94, 95, 96};
public static final int[] TRANSMIT_OFFSET = { 97,98,99,112,113,114,115,116, public static final int[] TRANSMIT_OFFSET = {97, 98, 99, 112, 113, 114, 115, 116,
117 }; 117};
public static final int[] CHANNEL_SPACING = { 118,119,120,121,122,123,136, public static final int[] CHANNEL_SPACING = {118, 119, 120, 121, 122, 123, 136,
137,138,139 }; 137, 138, 139};
public static final int[] BASE_FREQUENCY = { 140,141,142,143,144,145,146, public static final int[] BASE_FREQUENCY = {140, 141, 142, 143, 144, 145, 146,
147,160,161,162,163,164,165,166,167,168,169,170,171,184,185,186, 147, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 184, 185, 186,
187,188,189,190,191,192,193,194,195 }; 187, 188, 189, 190, 191, 192, 193, 194, 195};
public ChannelIdentifierUpdate( TDULinkControlMessage source ) public ChannelIdentifierUpdate(TDULinkControlMessage source)
{ {
super( source ); super(source);
} }
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE.getDescription(); return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " IDEN:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() ); sb.append(getMessageStub());
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() );
return sb.toString();
}
@Override sb.append(" IDEN:" + getIdentifier());
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
/** sb.append(" BASE:" + getBaseFrequency());
sb.append(" BW:" + getBandwidth());
sb.append(" SPACING:" + getChannelSpacing());
sb.append(" OFFSET:" + getTransmitOffset());
return sb.toString();
}
@Override
public int getIdentifier()
{
return mMessage.getInt(IDENTIFIER);
}
/**
* Channel bandwidth in hertz * Channel bandwidth in hertz
*/ */
@Override @Override
public int getBandwidth() public int getBandwidth()
{ {
return mMessage.getInt( BANDWIDTH ) * 125; return mMessage.getInt(BANDWIDTH) * 125;
} }
@Override @Override
public long getChannelSpacing() public long getChannelSpacing()
{ {
return mMessage.getLong( CHANNEL_SPACING ) * 125l; return mMessage.getLong(CHANNEL_SPACING) * 125l;
} }
@Override @Override
public long getBaseFrequency() public long getBaseFrequency()
{ {
return mMessage.getLong( BASE_FREQUENCY ) * 5l; return mMessage.getLong(BASE_FREQUENCY) * 5l;
} }
@Override @Override
public long getTransmitOffset() public long getTransmitOffset()
{ {
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l; return -1 * mMessage.getLong(TRANSMIT_OFFSET) * 250000l;
}
@Override
public long getDownlinkFrequency(int channelNumber)
{
return getBaseFrequency() + (channelNumber * getChannelSpacing());
}
@Override
public long getUplinkFrequency(int channelNumber)
{
return getDownlinkFrequency(channelNumber) + getTransmitOffset();
}
@Override
public boolean isTDMA()
{
return false;
} }
} }

View File

@@ -1,82 +1,114 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
public class ChannelIdentifierUpdateExplicit extends TDULinkControlMessage public class ChannelIdentifierUpdateExplicit extends TDULinkControlMessage implements IBandIdentifier
implements IBandIdentifier
{ {
public static final int[] IDENTIFIER = { 72,73,74,75 }; public static final int[] IDENTIFIER = {72, 73, 74, 75};
public static final int[] BANDWIDTH = { 88,89,90,91 }; public static final int[] BANDWIDTH = {88, 89, 90, 91};
public static final int[] TRANSMIT_OFFSET = { 92,93,94,95,96,97,98,99,112, public static final int[] TRANSMIT_OFFSET = {92, 93, 94, 95, 96, 97, 98, 99, 112, 113, 114, 115, 116, 117};
113,114,115,116,117 }; public static final int[] CHANNEL_SPACING = {118, 119, 120, 121, 122, 123, 136, 137, 138, 139};
public static final int[] CHANNEL_SPACING = { 118,119,120,121,122, public static final int[] BASE_FREQUENCY = {140, 141, 142, 143, 144, 145, 146, 147, 160, 161, 162, 163, 164, 165,
123,136,137,138,139 }; 166, 167, 168, 169, 170, 171, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195};
public static final int[] BASE_FREQUENCY = { 140,141,142,143,144,145,146,
147,160,161,162,163,164,165,166,167,168,169,170,171,184,185,186, public ChannelIdentifierUpdateExplicit(TDULinkControlMessage source)
187,188,189,190,191,192,193,194,195 }; {
super(source);
public ChannelIdentifierUpdateExplicit( TDULinkControlMessage source ) }
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE_EXPLICIT.getDescription(); return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " IDEN:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() ); sb.append(getMessageStub());
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() );
return sb.toString();
}
@Override sb.append(" IDEN:" + getIdentifier());
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
/** sb.append(" BASE:" + getBaseFrequency());
sb.append(" BW:" + getBandwidth());
sb.append(" SPACING:" + getChannelSpacing());
sb.append(" OFFSET:" + getTransmitOffset());
return sb.toString();
}
@Override
public int getIdentifier()
{
return mMessage.getInt(IDENTIFIER);
}
/**
* Channel bandwidth in hertz * Channel bandwidth in hertz
*/ */
@Override @Override
public int getBandwidth() public int getBandwidth()
{ {
return mMessage.getInt( BANDWIDTH ) * 125; return mMessage.getInt(BANDWIDTH) * 125;
} }
@Override @Override
public long getChannelSpacing() public long getChannelSpacing()
{ {
return mMessage.getLong( CHANNEL_SPACING ) * 125l; return mMessage.getLong(CHANNEL_SPACING) * 125l;
} }
@Override @Override
public long getBaseFrequency() public long getBaseFrequency()
{ {
return mMessage.getLong( BASE_FREQUENCY ) * 5l; return mMessage.getLong(BASE_FREQUENCY) * 5l;
} }
@Override @Override
public long getTransmitOffset() public long getTransmitOffset()
{ {
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l; return -1 * mMessage.getLong(TRANSMIT_OFFSET) * 250000l;
}
@Override
public long getDownlinkFrequency(int channelNumber)
{
return getBaseFrequency() + (channelNumber * getChannelSpacing());
}
@Override
public long getUplinkFrequency(int channelNumber)
{
return getDownlinkFrequency(channelNumber) + getTransmitOffset();
}
@Override
public boolean isTDMA()
{
return false;
} }
} }

View File

@@ -1,176 +1,207 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import java.util.Set;
import java.util.TreeSet;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class GroupVoiceChannelUpdate extends TDULinkControlMessage import java.util.Set;
implements IdentifierReceiver import java.util.TreeSet;
{
private final static Logger mLog = public class GroupVoiceChannelUpdate extends TDULinkControlMessage implements IdentifierReceiver
LoggerFactory.getLogger( GroupVoiceChannelUpdate.class ); {
public static final int[] IDENTIFIER_A = {72, 73, 74, 75};
public static final int[] CHANNEL_A = {88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99};
public static final int[] GROUP_ADDRESS_A = {112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 136, 137, 138, 139};
public static final int[] IDENTIFIER_B = {140, 141, 142, 143};
public static final int[] CHANNEL_B = {144, 145, 146, 147, 160, 161, 162, 163, 164, 165, 166, 167};
public static final int[] GROUP_ADDRESS_B = {168, 169, 170, 171, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195};
private IBandIdentifier mIdentifierUpdateA;
private IBandIdentifier mIdentifierUpdateB;
public GroupVoiceChannelUpdate(TDULinkControlMessage source)
{
super(source);
}
public static final int[] IDENTIFIER_A = { 72,73,74,75 };
public static final int[] CHANNEL_A = { 88,89,90,91,92,93,94,95,96,97,98,99 };
public static final int[] GROUP_ADDRESS_A = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139 };
public static final int[] IDENTIFIER_B = { 140,141,142,143 };
public static final int[] CHANNEL_B = { 144,145,146,147,160,161,162,163,164,
165,166,167 };
public static final int[] GROUP_ADDRESS_B = { 168,169,170,171,184,185,186,
187,188,189,190,191,192,193,194,195 };
private IBandIdentifier mIdentifierUpdateA;
private IBandIdentifier mIdentifierUpdateB;
public GroupVoiceChannelUpdate( TDULinkControlMessage source )
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE.getDescription(); return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append(getMessageStub());
sb.append( " CHAN A:" + getChannelA() ); sb.append(" CHAN A:" + getChannelA());
sb.append( " GRP A:" + getGroupAddressA() ); sb.append(" GRP A:" + getGroupAddressA());
if( hasChannelB() ) if(hasChannelB())
{ {
sb.append( " CHAN B:" + getChannelA() ); sb.append(" CHAN B:" + getChannelA());
sb.append( " GRP B:" + getGroupAddressA() ); sb.append(" GRP B:" + getGroupAddressA());
} }
return sb.toString(); return sb.toString();
} }
public int getChannelIdentifierA()
{
return mMessage.getInt(IDENTIFIER_A);
}
public int getChannelIdentifierA()
{
return mMessage.getInt( IDENTIFIER_A );
}
public int getChannelNumberA() public int getChannelNumberA()
{ {
return mMessage.getInt( CHANNEL_A ); return mMessage.getInt(CHANNEL_A);
} }
public String getChannelA() public String getChannelA()
{ {
return getChannelIdentifierA() + "-" + getChannelNumberA(); return getChannelIdentifierA() + "-" + getChannelNumberA();
} }
public int getChannelIdentifierB() public int getChannelIdentifierB()
{ {
return mMessage.getInt( IDENTIFIER_B ); return mMessage.getInt(IDENTIFIER_B);
} }
public int getChannelNumberB() public int getChannelNumberB()
{ {
return mMessage.getInt( CHANNEL_B ); return mMessage.getInt(CHANNEL_B);
} }
public String getChannelB() public String getChannelB()
{ {
return getChannelIdentifierB() + "-" + getChannelNumberB(); return getChannelIdentifierB() + "-" + getChannelNumberB();
} }
public boolean hasChannelB() public boolean hasChannelB()
{ {
return getChannelNumberB() != 0; return getChannelNumberB() != 0;
} }
public String getGroupAddressA() public String getGroupAddressA()
{ {
return mMessage.getHex( GROUP_ADDRESS_A, 4 ); return mMessage.getHex(GROUP_ADDRESS_A, 4);
} }
public String getGroupAddressB() public String getGroupAddressB()
{ {
return mMessage.getHex( GROUP_ADDRESS_B, 4 ); return mMessage.getHex(GROUP_ADDRESS_B, 4);
} }
/** /**
* Returns a sorted list of addresses contained in the A and B fields * Returns a sorted list of addresses contained in the A and B fields
* @return *
*/ * @return
public Set<String> getAddresses() */
{ public Set<String> getAddresses()
Set<String> addresses = new TreeSet<String>();
addresses.add( getGroupAddressA() );
addresses.add( getGroupAddressB() );
return addresses;
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getChannelIdentifierA() ) Set<String> addresses = new TreeSet<String>();
{
mIdentifierUpdateA = message; addresses.add(getGroupAddressA());
} addresses.add(getGroupAddressB());
if( identifier == getChannelIdentifierB() )
{ return addresses;
mIdentifierUpdateB = message;
}
} }
@Override
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getChannelIdentifierA())
{
mIdentifierUpdateA = message;
}
if(identifier == getChannelIdentifierB())
{
mIdentifierUpdateB = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
if( hasChannelB() ) if(hasChannelB())
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getChannelIdentifierA(); identifiers[0] = getChannelIdentifierA();
identifiers[ 1 ] = getChannelIdentifierB(); identifiers[1] = getChannelIdentifierB();
return identifiers; return identifiers;
} }
else else
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getChannelIdentifierA(); identifiers[0] = getChannelIdentifierA();
return identifiers; return identifiers;
} }
} }
public long getDownlinkFrequencyA() public long getDownlinkFrequencyA()
{ {
return calculateDownlink( mIdentifierUpdateA, getChannelNumberA() ); if(mIdentifierUpdateA != null)
{
return mIdentifierUpdateA.getDownlinkFrequency(getChannelNumberA());
}
return 0;
} }
public long getUplinkFrequencyA() public long getUplinkFrequencyA()
{ {
return calculateUplink( mIdentifierUpdateA, getChannelNumberA() ); if(mIdentifierUpdateA != null)
{
return mIdentifierUpdateA.getUplinkFrequency(getChannelNumberA());
}
return 0;
} }
public long getDownlinkFrequencyB() public long getDownlinkFrequencyB()
{ {
return calculateDownlink( mIdentifierUpdateB, getChannelNumberA() ); if(mIdentifierUpdateB != null)
{
return mIdentifierUpdateB.getDownlinkFrequency(getChannelNumberB());
}
return 0;
} }
public long getUplinkFrequencyB() public long getUplinkFrequencyB()
{ {
return calculateUplink( mIdentifierUpdateB, getChannelNumberA() ); if(mIdentifierUpdateB != null)
{
return mIdentifierUpdateB.getUplinkFrequency(getChannelNumberB());
}
return 0;
} }
} }

View File

@@ -1,154 +1,176 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class GroupVoiceChannelUpdateExplicit extends TDULinkControlMessage public class GroupVoiceChannelUpdateExplicit extends TDULinkControlMessage
implements IdentifierReceiver implements IdentifierReceiver
{ {
private final static Logger mLog = private final static Logger mLog =
LoggerFactory.getLogger( GroupVoiceChannelUpdateExplicit.class ); LoggerFactory.getLogger(GroupVoiceChannelUpdateExplicit.class);
public static final int EMERGENCY_FLAG = 92; public static final int EMERGENCY_FLAG = 92;
public static final int ENCRYPTED_CHANNEL_FLAG = 93; public static final int ENCRYPTED_CHANNEL_FLAG = 93;
public static final int DUPLEX_MODE = 94; public static final int DUPLEX_MODE = 94;
public static final int SESSION_MODE = 95; public static final int SESSION_MODE = 95;
public static final int[] GROUP_ADDRESS = { 112,113,114,115,116,117,118, public static final int[] GROUP_ADDRESS = {112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 136, 137, 138, 139};
119,120,121,122,123,136,137,138,139 }; public static final int[] TRANSMIT_IDENTIFIER = {140, 141, 142, 143};
public static final int[] TRANSMIT_IDENTIFIER = { 140,141,142,143 }; public static final int[] TRANSMIT_CHANNEL = {144, 145, 146, 147, 160, 161, 162, 163, 164, 165, 166, 167};
public static final int[] TRANSMIT_CHANNEL = { 144,145,146,147,160,161,162, public static final int[] RECEIVE_IDENTIFIER = {168, 169, 170, 171};
163,164,165,166,167 }; public static final int[] RECEIVE_CHANNEL = {184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199};
public static final int[] RECEIVE_IDENTIFIER = { 168,169,170,171 };
public static final int[] RECEIVE_CHANNEL = { 184,185,186,187,188,189,190, private IBandIdentifier mTransmitIdentifierUpdate;
191,192,193,194,195,196,197,198,199 }; private IBandIdentifier mReceiveIdentifierUpdate;
private IBandIdentifier mTransmitIdentifierUpdate; public GroupVoiceChannelUpdateExplicit(TDULinkControlMessage source)
private IBandIdentifier mReceiveIdentifierUpdate; {
super(source);
public GroupVoiceChannelUpdateExplicit( TDULinkControlMessage source ) }
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT.getDescription(); return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
if( isEncryptedChannel() )
{
sb.append( " ENCRYPTED CHANNEL" );
}
sb.append(getMessageStub());
return sb.toString();
} if(isEmergency())
{
sb.append(" EMERGENCY");
}
if(isEncryptedChannel())
{
sb.append(" ENCRYPTED CHANNEL");
}
return sb.toString();
}
public boolean isEmergency() public boolean isEmergency()
{ {
return mMessage.get( EMERGENCY_FLAG ); return mMessage.get(EMERGENCY_FLAG);
} }
public boolean isEncryptedChannel() public boolean isEncryptedChannel()
{ {
return mMessage.get( ENCRYPTED_CHANNEL_FLAG ); return mMessage.get(ENCRYPTED_CHANNEL_FLAG);
} }
public DuplexMode getDuplexMode() public DuplexMode getDuplexMode()
{ {
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF; return mMessage.get(DUPLEX_MODE) ? DuplexMode.FULL : DuplexMode.HALF;
} }
public SessionMode getSessionMode() public SessionMode getSessionMode()
{ {
return mMessage.get( SESSION_MODE ) ? return mMessage.get(SESSION_MODE) ?
SessionMode.CIRCUIT : SessionMode.PACKET; SessionMode.CIRCUIT : SessionMode.PACKET;
} }
public int getTransmitChannelIdentifier() public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{ {
return mMessage.getInt( TRANSMIT_CHANNEL ); return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitChannelIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveChannelIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
} }
@Override public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public String getGroupAddress()
{
return mMessage.getHex(GROUP_ADDRESS, 4);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitChannelIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveChannelIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitChannelIdentifier(); identifiers[0] = getTransmitChannelIdentifier();
identifiers[ 1 ] = getReceiveChannelIdentifier(); identifiers[1] = getReceiveChannelIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitIdentifierUpdate, if(mTransmitIdentifierUpdate != null)
getTransmitChannelNumber() ); {
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveIdentifierUpdate, if(mReceiveIdentifierUpdate != null)
getReceiveChannelNumber() ); {
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -5,106 +23,106 @@ import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import module.decode.p25.reference.Service; import module.decode.p25.reference.Service;
import org.slf4j.Logger; public class NetworkStatusBroadcast extends TDULinkControlMessage implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class NetworkStatusBroadcast extends TDULinkControlMessage
implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] WACN = {72, 73, 74, 75, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 112, 113, 114,
LoggerFactory.getLogger( NetworkStatusBroadcast.class ); 115, 116, 117, 118, 119, 120, 121, 122, 123};
public static final int[] SYSTEM = {136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147};
public static final int[] WACN = { 72,73,74,75,88,89,90,91,92,93,94,95,96, public static final int[] IDENTIFIER = {160, 161, 162, 163};
97,98,99,112,113,114,115,116,117,118,119,120,121,122,123 }; public static final int[] CHANNEL = {164, 165, 166, 167, 168, 169, 170, 171, 184, 185, 186, 187};
public static final int[] SYSTEM = { 136,137,138,139,140,141,142,143,144, public static final int[] SYSTEM_SERVICE_CLASS = {188, 189, 190, 191, 192, 193, 194, 195};
145,146,147 };
public static final int[] IDENTIFIER = { 160,161,162,163 }; private IBandIdentifier mIdentifierUpdate;
public static final int[] CHANNEL = { 164,165,166,167,168,169,170,171,184,
185,186,187 }; public NetworkStatusBroadcast(TDULinkControlMessage source)
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193, {
194,195 }; super(source);
}
private IBandIdentifier mIdentifierUpdate;
public NetworkStatusBroadcast( TDULinkControlMessage source )
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.NETWORK_STATUS_BROADCAST.getDescription(); return LinkControlOpcode.NETWORK_STATUS_BROADCAST.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " NETWORK:" + getWACN() );
sb.append( " SYS:" + getSystem() );
sb.append( " CHAN:" + getChannel() );
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
return sb.toString();
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getSystem()
{
return mMessage.getHex( SYSTEM, 3 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
mIdentifierUpdate = message; StringBuilder sb = new StringBuilder();
sb.append(getMessageStub());
sb.append(" NETWORK:" + getWACN());
sb.append(" SYS:" + getSystem());
sb.append(" CHAN:" + getChannel());
sb.append(" " + Service.getServices(getSystemServiceClass()).toString());
return sb.toString();
} }
@Override public String getWACN()
{
return mMessage.getHex(WACN, 5);
}
public String getSystem()
{
return mMessage.getHex(SYSTEM, 3);
}
public int getIdentifier()
{
return mMessage.getInt(IDENTIFIER);
}
public int getChannelNumber()
{
return mMessage.getInt(CHANNEL);
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
mIdentifierUpdate = message;
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getIdentifier(); identifiers[0] = getIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getDownlinkFrequency(getChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getUplinkFrequency(getChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,131 +1,146 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; public class NetworkStatusBroadcastExplicit extends TDULinkControlMessage implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class NetworkStatusBroadcastExplicit extends TDULinkControlMessage
implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] WACN = {72, 73, 74, 75, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 112, 113, 114, 115};
LoggerFactory.getLogger( NetworkStatusBroadcastExplicit.class ); public static final int[] SYSTEM = {116, 117, 118, 119, 120, 121, 122, 123, 136, 137, 138, 139};
public static final int[] TRANSMIT_IDENTIFIER = {140, 141, 142, 143};
public static final int[] TRANSMIT_CHANNEL = {144, 145, 146, 147, 160, 161, 162, 163, 164, 165, 166, 167};
public static final int[] RECEIVE_IDENTIFIER = {168, 169, 170, 171};
public static final int[] RECEIVE_CHANNEL = {184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195};
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public NetworkStatusBroadcastExplicit(TDULinkControlMessage source)
{
super(source);
}
public static final int[] WACN = { 72,73,74,75,88,89,90,91,92,93,94,95,96,
97,98,99,112,113,114,115 };
public static final int[] SYSTEM = { 116,117,118,119,120,121,122,123,136,
137,138,139 };
public static final int[] TRANSMIT_IDENTIFIER = { 140,141,142,143 };
public static final int[] TRANSMIT_CHANNEL = { 144,145,146,147,160,161,162,
163,164,165,166,167 };
public static final int[] RECEIVE_IDENTIFIER = { 168,169,170,171 };
public static final int[] RECEIVE_CHANNEL = { 184,185,186,187,188,189,190,
191,192,193,194,195 };
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public NetworkStatusBroadcastExplicit( TDULinkControlMessage source )
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.NETWORK_STATUS_BROADCAST_EXPLICIT.getDescription(); return LinkControlOpcode.NETWORK_STATUS_BROADCAST_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " NETWORK:" + getWACN() );
sb.append( " SYS:" + getSystem() );
sb.append( " TRANSMIT:" + getTransmitChannel() );
sb.append( " RECEIVE:" + getReceiveChannel() );
return sb.toString();
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getSystem()
{
return mMessage.getHex( SYSTEM, 3 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitIdentifier() ) StringBuilder sb = new StringBuilder();
{
mTransmitIdentifierUpdate = message; sb.append(getMessageStub());
}
if( identifier == getReceiveIdentifier() ) sb.append(" NETWORK:" + getWACN());
{ sb.append(" SYS:" + getSystem());
mReceiveIdentifierUpdate = message; sb.append(" TRANSMIT:" + getTransmitChannel());
} sb.append(" RECEIVE:" + getReceiveChannel());
return sb.toString();
} }
@Override public String getWACN()
{
return mMessage.getHex(WACN, 5);
}
public String getSystem()
{
return mMessage.getHex(SYSTEM, 3);
}
public int getTransmitIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitIdentifier(); identifiers[0] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier(); identifiers[1] = getReceiveIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitIdentifierUpdate, if(mTransmitIdentifierUpdate != null)
getTransmitChannelNumber() ); {
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveIdentifierUpdate, if(mReceiveIdentifierUpdate != null)
getReceiveChannelNumber() ); {
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -5,128 +23,124 @@ import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; public class RFSSStatusBroadcast extends TDULinkControlMessage implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class RFSSStatusBroadcast extends TDULinkControlMessage
implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] LRA = {72, 73, 74, 75, 88, 89, 90, 91};
LoggerFactory.getLogger( RFSSStatusBroadcast.class ); public static final int[] SYSTEM_ID = {96, 97, 98, 99, 112, 113, 114, 115, 116, 117, 118, 119};
public static final int[] RFSS_ID = {120, 121, 122, 123, 136, 137, 138, 139};
public static final int[] SITE_ID = {140, 141, 142, 143, 144, 145, 146, 147};
public static final int[] IDENTIFIER = {160, 161, 162, 163};
public static final int[] CHANNEL = {164, 165, 166, 167, 168, 169, 170, 171, 184, 185, 186, 187};
public static final int[] SYSTEM_SERVICE_CLASS = {188, 189, 190, 191, 192, 193, 194, 195};
private IBandIdentifier mIdentifierUpdate;
public RFSSStatusBroadcast(TDULinkControlMessage source)
{
super(source);
}
public static final int[] LRA = { 72,73,74,75,88,89,
90,91 };
public static final int[] SYSTEM_ID = { 96,97,98,99,112,113,114,115,116,117,
118,119 };
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,
139 };
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 };
public static final int[] IDENTIFIER = { 160,161,162,163 };
public static final int[] CHANNEL = { 164,165,166,167,168,169,170,
171,184,185,186,187 };
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193,
194,195 };
private IBandIdentifier mIdentifierUpdate;
public RFSSStatusBroadcast( TDULinkControlMessage source )
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.RFSS_STATUS_BROADCAST.getDescription(); return LinkControlOpcode.RFSS_STATUS_BROADCAST.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SYS:" + getSystem() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " CHAN:" + getChannelNumber() );
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
sb.append( " " + mMessage.toString() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getSystem()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
mIdentifierUpdate = message; StringBuilder sb = new StringBuilder();
sb.append(getMessageStub());
sb.append(" LRA:" + getLocationRegistrationArea());
sb.append(" SYS:" + getSystem());
sb.append(" SITE:" + getRFSubsystemID() + "-" + getSiteID());
sb.append(" CHAN:" + getChannelNumber());
sb.append(" " + SystemService.toString(getSystemServiceClass()));
sb.append(" " + mMessage.toString());
return sb.toString();
} }
@Override public String getLocationRegistrationArea()
{
return mMessage.getHex(LRA, 2);
}
public String getSystem()
{
return mMessage.getHex(SYSTEM_ID, 3);
}
public String getRFSubsystemID()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getIdentifier()
{
return mMessage.getInt(IDENTIFIER);
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getChannelNumber()
{
return mMessage.getInt(CHANNEL);
}
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
mIdentifierUpdate = message;
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getIdentifier(); identifiers[0] = getIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getDownlinkFrequency(getChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getUplinkFrequency(getChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,152 +1,171 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class RFSSStatusBroadcastExplicit extends TDULinkControlMessage public class RFSSStatusBroadcastExplicit extends TDULinkControlMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
private final static Logger mLog = private final static Logger mLog = LoggerFactory.getLogger(RFSSStatusBroadcastExplicit.class);
LoggerFactory.getLogger( RFSSStatusBroadcastExplicit.class );
public static final int[] LRA = {72, 73, 74, 75, 88, 89, 90, 91};
public static final int[] RECEIVE_IDENTIFIER = {92, 93, 94, 95};
public static final int[] RECEIVE_CHANNEL = {96, 97, 98, 99, 112, 113, 114, 115, 116, 117, 118, 119};
public static final int[] RFSS_ID = {120, 121, 122, 123, 136, 137, 138, 139};
public static final int[] SITE_ID = {140, 141, 142, 143, 144, 145, 146, 147};
public static final int[] TRANSMIT_IDENTIFIER = {160, 161, 162, 163};
public static final int[] TRANSMIT_CHANNEL = {164, 165, 166, 167, 168, 169, 170, 171, 184, 185, 186, 187};
public static final int[] SYSTEM_SERVICE_CLASS = {188, 189, 190, 191, 192, 193, 194, 195};
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public RFSSStatusBroadcastExplicit(TDULinkControlMessage source)
{
super(source);
}
public static final int[] LRA = { 72,73,74,75,88,89,90,91 };
public static final int[] RECEIVE_IDENTIFIER = { 92,93,94,95 };
public static final int[] RECEIVE_CHANNEL = { 96,97,98,99,112,113,114,115,
116,117,118,119 };
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,
139 };
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 };
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 };
public static final int[] TRANSMIT_CHANNEL = { 164,165,166,167,168,169,170,
171,184,185,186,187 };
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193,
194,195 };
private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public RFSSStatusBroadcastExplicit( TDULinkControlMessage source )
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.RFSS_STATUS_BROADCAST_EXPLICIT.getDescription(); return LinkControlOpcode.RFSS_STATUS_BROADCAST_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " TRANSMIT:" + getTransmitChannelNumber() );
sb.append( " RECEIVE:" + getReceiveChannelNumber() );
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
sb.append( " " + mMessage.toString() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitIdentifier() ) StringBuilder sb = new StringBuilder();
{
mTransmitIdentifierUpdate = message; sb.append(getMessageStub());
}
sb.append(" LRA:" + getLocationRegistrationArea());
if( identifier == getReceiveIdentifier() )
{ sb.append(" SITE:" + getRFSubsystemID() + "-" + getSiteID());
mReceiveIdentifierUpdate = message;
} sb.append(" TRANSMIT:" + getTransmitChannelNumber());
sb.append(" RECEIVE:" + getReceiveChannelNumber());
sb.append(" " + SystemService.toString(getSystemServiceClass()));
sb.append(" " + mMessage.toString());
return sb.toString();
} }
@Override public String getLocationRegistrationArea()
{
return mMessage.getHex(LRA, 2);
}
public String getRFSubsystemID()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getTransmitIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public int getReceiveIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitIdentifier(); identifiers[0] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier(); identifiers[1] = getReceiveIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() ); if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() ); if(mReceiveIdentifierUpdate != null)
{
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -5,155 +23,162 @@ import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; public class SecondaryControlChannelBroadcast extends TDULinkControlMessage implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class SecondaryControlChannelBroadcast extends TDULinkControlMessage
implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] RFSS_ID = {72, 73, 74, 75, 88, 89, 90, 91};
LoggerFactory.getLogger( SecondaryControlChannelBroadcast.class ); public static final int[] SITE_ID = {92, 93, 94, 95, 96, 97, 98, 99};
public static final int[] IDENTIFIER_A = {112, 113, 114, 115};
public static final int[] CHANNEL_A = {116, 117, 118, 119, 120, 121, 122, 123, 136, 137, 138, 139};
public static final int[] SYSTEM_SERVICE_CLASS_A = {140, 141, 142, 143, 144, 145, 146, 147};
public static final int[] IDENTIFIER_B = {160, 161, 162, 163};
public static final int[] CHANNEL_B = {164, 165, 166, 167, 168, 169, 170, 171, 184, 185, 186, 187};
public static final int[] SYSTEM_SERVICE_CLASS_B = {188, 189, 190, 191, 192, 193, 194, 195};
private IBandIdentifier mIdentifierProviderA;
private IBandIdentifier mIdentifierProviderB;
public SecondaryControlChannelBroadcast(TDULinkControlMessage source)
{
super(source);
}
public static final int[] RFSS_ID = { 72,73,74,75,88,89,90,91 };
public static final int[] SITE_ID = { 92,93,94,95,96,97,98,99 };
public static final int[] IDENTIFIER_A = { 112,113,114,115 };
public static final int[] CHANNEL_A = { 116,117,118,119,120,121,122,
123,136,137,138,139 };
public static final int[] SYSTEM_SERVICE_CLASS_A = { 140,141,142,143,144,
145,146,147 };
public static final int[] IDENTIFIER_B = { 160,161,162,163 };
public static final int[] CHANNEL_B = { 164,165,166,167,168,169,170,
171,184,185,186,187 };
public static final int[] SYSTEM_SERVICE_CLASS_B = { 188,189,190,191,192,
193,194,195 };
private IBandIdentifier mIdentifierProviderA;
private IBandIdentifier mIdentifierProviderB;
public SecondaryControlChannelBroadcast( TDULinkControlMessage source )
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST.getDescription(); return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " CHAN A:" + getChannelA() );
sb.append( " " + SystemService.toString( getSystemServiceClassA() ) );
sb.append( " CHAN B:" + getChannelB() );
sb.append( " " + SystemService.toString( getSystemServiceClassB() ) );
return sb.toString();
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifierA()
{
return mMessage.getInt( IDENTIFIER_A );
}
public int getChannelA()
{
return mMessage.getInt( CHANNEL_A );
}
public String getChannelNumberA()
{
return getIdentifierA() + "-" + getChannelA();
}
public int getIdentifierB()
{
return mMessage.getInt( IDENTIFIER_B );
}
public int getChannelB()
{
return mMessage.getInt( CHANNEL_B );
}
public String getChannelNumberB()
{
return getIdentifierB() + "-" + getChannelB();
}
public int getSystemServiceClassA()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS_A );
}
public int getSystemServiceClassB()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS_B );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getIdentifierA() ) StringBuilder sb = new StringBuilder();
{
mIdentifierProviderA = message; sb.append(getMessageStub());
}
if( identifier == getIdentifierB() ) sb.append(" SITE:" + getRFSubsystemID() + "-" + getSiteID());
{
mIdentifierProviderB = message; sb.append(" CHAN A:" + getChannelA());
}
sb.append(" " + SystemService.toString(getSystemServiceClassA()));
sb.append(" CHAN B:" + getChannelB());
sb.append(" " + SystemService.toString(getSystemServiceClassB()));
return sb.toString();
} }
@Override public String getRFSubsystemID()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getIdentifierA()
{
return mMessage.getInt(IDENTIFIER_A);
}
public int getChannelA()
{
return mMessage.getInt(CHANNEL_A);
}
public String getChannelNumberA()
{
return getIdentifierA() + "-" + getChannelA();
}
public int getIdentifierB()
{
return mMessage.getInt(IDENTIFIER_B);
}
public int getChannelB()
{
return mMessage.getInt(CHANNEL_B);
}
public String getChannelNumberB()
{
return getIdentifierB() + "-" + getChannelB();
}
public int getSystemServiceClassA()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS_A);
}
public int getSystemServiceClassB()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS_B);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getIdentifierA())
{
mIdentifierProviderA = message;
}
if(identifier == getIdentifierB())
{
mIdentifierProviderB = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getIdentifierA(); identifiers[0] = getIdentifierA();
identifiers[ 1 ] = getIdentifierB(); identifiers[1] = getIdentifierB();
return identifiers; return identifiers;
} }
public long getDownlinkFrequencyA() public long getDownlinkFrequencyA()
{ {
return calculateDownlink( mIdentifierProviderA, getChannelA() ); if(mIdentifierProviderA != null)
{
return mIdentifierProviderA.getDownlinkFrequency(getChannelA());
}
return 0;
} }
public long getUplinkFrequencyA() public long getUplinkFrequencyA()
{ {
return calculateUplink( mIdentifierProviderA, getChannelA() ); if(mIdentifierProviderA != null)
{
return mIdentifierProviderA.getUplinkFrequency(getChannelA());
}
return 0;
} }
public long getDownlinkFrequencyB() public long getDownlinkFrequencyB()
{ {
return calculateDownlink( mIdentifierProviderB, getChannelB() ); if(mIdentifierProviderB != null)
{
return mIdentifierProviderB.getDownlinkFrequency(getChannelB());
}
return 0;
} }
public long getUplinkFrequencyB() public long getUplinkFrequencyB()
{ {
return calculateUplink( mIdentifierProviderB, getChannelB() ); if(mIdentifierProviderB != null)
{
return mIdentifierProviderB.getUplinkFrequency(getChannelB());
}
return 0;
} }
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tdu.lc; package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -5,136 +23,134 @@ import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.osp.control.SystemService; import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode; import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger; public class SecondaryControlChannelBroadcastExplicit extends TDULinkControlMessage implements IdentifierReceiver
import org.slf4j.LoggerFactory;
public class SecondaryControlChannelBroadcastExplicit
extends TDULinkControlMessage implements IdentifierReceiver
{ {
private final static Logger mLog = public static final int[] RFSS_ID = {72, 73, 74, 75, 88, 89, 90, 91};
LoggerFactory.getLogger( SecondaryControlChannelBroadcastExplicit.class ); public static final int[] SITE_ID = {92, 93, 94, 95, 96, 97, 98, 99};
public static final int[] TRANSMIT_IDENTIFIER = {112, 113, 114, 115};
public static final int[] TRANSMIT_CHANNEL = {116, 117, 118, 119, 120, 121, 122, 123, 136, 137, 138, 139};
public static final int[] RECEIVE_IDENTIFIER = {140, 141, 142, 143};
public static final int[] RECEIVE_CHANNEL = {144, 145, 146, 147, 160, 161, 162, 163, 164, 165, 166, 167};
public static final int[] SYSTEM_SERVICE_CLASS = {168, 169, 170, 171, 184, 185, 186, 187};
private IBandIdentifier mTransmitIdentifierProvider;
private IBandIdentifier mReceiveIdentifierProvider;
public SecondaryControlChannelBroadcastExplicit(TDULinkControlMessage source)
{
super(source);
}
public static final int[] RFSS_ID = { 72,73,74,75,88,89,90,91 };
public static final int[] SITE_ID = { 92,93,94,95,96,97,98,99 };
public static final int[] TRANSMIT_IDENTIFIER = { 112,113,114,115 };
public static final int[] TRANSMIT_CHANNEL = { 116,117,118,119,120,121,122,
123,136,137,138,139 };
public static final int[] RECEIVE_IDENTIFIER = { 140,141,142,143 };
public static final int[] RECEIVE_CHANNEL = { 144,145,146,147,160,161,162,
163,164,165,166,167 };
public static final int[] SYSTEM_SERVICE_CLASS = { 168,169,170,171,184,
185,186,187 };
private IBandIdentifier mTransmitIdentifierProvider;
private IBandIdentifier mReceiveIdentifierProvider;
public SecondaryControlChannelBroadcastExplicit( TDULinkControlMessage source )
{
super( source );
}
@Override @Override
public String getEventType() public String getEventType()
{ {
return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT.getDescription(); return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT.getDescription();
} }
@Override @Override
public String getMessage() public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " TRANSMIT:" + getTransmitChannel() );
sb.append( " RECEIVE:" + getReceiveChannel() );
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
return sb.toString();
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
if( identifier == getTransmitIdentifier() ) StringBuilder sb = new StringBuilder();
{
mTransmitIdentifierProvider = message; sb.append(getMessageStub());
}
if( identifier == getReceiveIdentifier() ) sb.append(" SITE:" + getRFSubsystemID() + "-" + getSiteID());
{
mReceiveIdentifierProvider = message; sb.append(" TRANSMIT:" + getTransmitChannel());
}
sb.append(" RECEIVE:" + getReceiveChannel());
sb.append(" " + SystemService.toString(getSystemServiceClass()));
return sb.toString();
} }
@Override public String getRFSubsystemID()
{
return mMessage.getHex(RFSS_ID, 2);
}
public String getSiteID()
{
return mMessage.getHex(SITE_ID, 2);
}
public int getTransmitIdentifier()
{
return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_CHANNEL);
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_CHANNEL);
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitIdentifier())
{
mTransmitIdentifierProvider = message;
}
if(identifier == getReceiveIdentifier())
{
mReceiveIdentifierProvider = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitIdentifier(); identifiers[0] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier(); identifiers[1] = getReceiveIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitIdentifierProvider, if(mTransmitIdentifierProvider != null)
getTransmitChannelNumber() ); {
return mTransmitIdentifierProvider.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveIdentifierProvider, if(mReceiveIdentifierProvider != null)
getReceiveChannelNumber() ); {
return mReceiveIdentifierProvider.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,26 +1,53 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk; package module.decode.p25.message.tsbk;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import alias.AliasList;
import bits.BinaryMessage;
public abstract class ChannelGrant extends ServiceMessage public abstract class ChannelGrant extends ServiceMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
public static final int[] PRIORITY = { 85,86,87 }; public static final int[] PRIORITY = {85, 86, 87};
public static final int[] CHANNEL_IDENTIFIER = { 88,89,90,91 }; public static final int[] CHANNEL_IDENTIFIER = {88, 89, 90, 91};
public static final int[] CHANNEL_NUMBER = { 92,93,94,95,96,97,98,99,100, public static final int[] CHANNEL_NUMBER = {92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103};
101,102,103 };
private IBandIdentifier mIdentifierUpdate; private IBandIdentifier mIdentifierUpdate;
public ChannelGrant( BinaryMessage message, public ChannelGrant(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
}
/**
* Indicates if this channel grant is for a TDMA channel
*/
public boolean isTDMAChannel()
{
if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.isTDMA();
}
return false;
} }
/** /**
@@ -28,47 +55,56 @@ public abstract class ChannelGrant extends ServiceMessage
*/ */
public int getPriority() public int getPriority()
{ {
return mMessage.getInt( PRIORITY ); return mMessage.getInt(PRIORITY);
} }
public int getChannelIdentifier() public int getChannelIdentifier()
{ {
return mMessage.getInt( CHANNEL_IDENTIFIER ); return mMessage.getInt(CHANNEL_IDENTIFIER);
} }
public int getChannelNumber() public int getChannelNumber()
{ {
return mMessage.getInt( CHANNEL_NUMBER ); return mMessage.getInt(CHANNEL_NUMBER);
} }
public String getChannel() public String getChannel()
{ {
return getChannelIdentifier() + "-" + getChannelNumber(); return getChannelIdentifier() + "-" + getChannelNumber();
} }
@Override @Override
public void setIdentifierMessage( int identifier, IBandIdentifier message ) public void setIdentifierMessage(int identifier, IBandIdentifier message)
{ {
mIdentifierUpdate = message; mIdentifierUpdate = message;
} }
@Override @Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getChannelIdentifier(); identifiers[0] = getChannelIdentifier();
return identifiers; return identifiers;
}
public long getDownlinkFrequency()
{
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
} }
public long getDownlinkFrequency()
{
if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getDownlinkFrequency(getChannelNumber());
}
return 0;
}
public long getUplinkFrequency()
{
if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getUplinkFrequency(getChannelNumber());
}
return 0;
}
} }

View File

@@ -1,120 +1,155 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk; package module.decode.p25.message.tsbk;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.reference.DataUnitID;
import alias.AliasList; import alias.AliasList;
import bits.BinaryMessage; import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.reference.DataUnitID;
public abstract class GroupChannelGrantExplicit extends ChannelGrant public abstract class GroupChannelGrantExplicit extends ChannelGrant
{ {
public static final int[] TRANSMIT_IDENTIFIER = { 96,97,98,99 }; public static final int[] TRANSMIT_IDENTIFIER = {96, 97, 98, 99};
public static final int[] TRANSMIT_NUMBER = { 100,101,102,103, public static final int[] TRANSMIT_NUMBER = {100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111};
104,105,106,107,108,109,110,111 }; public static final int[] RECEIVE_IDENTIFIER = {112, 113, 114, 115};
public static final int[] RECEIVE_IDENTIFIER = { 112,113,114,115 }; public static final int[] RECEIVE_NUMBER = {116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127};
public static final int[] RECEIVE_NUMBER = { 116,117,118,119, public static final int[] GROUP_ADDRESS = {128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
120,121,122,123,124,125,126,127 }; 142, 143};
public static final int[] GROUP_ADDRESS = { 128,129,130,131,132,133,134,135,
136,137,138,139,140,141,142,143 };
private IBandIdentifier mTransmitIdentifierUpdate; private IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate; private IBandIdentifier mReceiveIdentifierUpdate;
public GroupChannelGrantExplicit( BinaryMessage message, public GroupChannelGrantExplicit(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
}
@Override
public boolean isTDMAChannel()
{
if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.isTDMA();
}
return false;
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append(getMessageStub());
if( isEmergency() ) if(isEmergency())
{ {
sb.append( " EMERGENCY" ); sb.append(" EMERGENCY");
} }
sb.append( " XMIT:" ); sb.append(" XMIT:");
sb.append( getTransmitChannelIdentifier() + "/" + getTransmitChannelNumber() ); sb.append(getTransmitChannelIdentifier() + "/" + getTransmitChannelNumber());
sb.append( " RCV:" ); sb.append(" RCV:");
sb.append( getReceiveChannelIdentifier() + "/" + getReceiveChannelNumber() ); sb.append(getReceiveChannelIdentifier() + "/" + getReceiveChannelNumber());
sb.append( " GRP:" ); sb.append(" GRP:");
sb.append( getGroupAddress() ); sb.append(getGroupAddress());
return sb.toString(); return sb.toString();
} }
public int getTransmitChannelIdentifier() public int getTransmitChannelIdentifier()
{ {
return mMessage.getInt( TRANSMIT_IDENTIFIER ); return mMessage.getInt(TRANSMIT_IDENTIFIER);
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitChannelIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveChannelIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
} }
@Override public int getTransmitChannelNumber()
{
return mMessage.getInt(TRANSMIT_NUMBER);
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt(RECEIVE_IDENTIFIER);
}
public int getReceiveChannelNumber()
{
return mMessage.getInt(RECEIVE_NUMBER);
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public String getGroupAddress()
{
return mMessage.getHex(GROUP_ADDRESS, 4);
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitChannelIdentifier())
{
mTransmitIdentifierUpdate = message;
}
if(identifier == getReceiveChannelIdentifier())
{
mReceiveIdentifierUpdate = message;
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitChannelIdentifier(); identifiers[0] = getTransmitChannelIdentifier();
identifiers[ 1 ] = getReceiveChannelIdentifier(); identifiers[1] = getReceiveChannelIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() ); if(mTransmitIdentifierUpdate != null)
{
return mTransmitIdentifierUpdate.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() ); if(mReceiveIdentifierUpdate != null)
{
return mReceiveIdentifierUpdate.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,106 +1,116 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk; package module.decode.p25.message.tsbk;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import alias.AliasList;
import bits.BinaryMessage;
public abstract class GroupMultiChannelGrant extends ChannelGrant public abstract class GroupMultiChannelGrant extends ChannelGrant implements IdentifierReceiver
implements IdentifierReceiver
{ {
public static final int[] CHANNEL_IDENTIFIER_1 = { 80,81,82,83 }; public static final int[] CHANNEL_IDENTIFIER_1 = {80, 81, 82, 83};
public static final int[] CHANNEL_NUMBER_1 = { 84,85,86,87, public static final int[] CHANNEL_NUMBER_1 = {84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95};
88,89,90,91,92,93,94,95 }; public static final int[] GROUP_ADDRESS_1 = {96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111};
public static final int[] GROUP_ADDRESS_1 = { 96,97,98,99,100,101,102,103, public static final int[] CHANNEL_IDENTIFIER_2 = {112, 113, 114, 115};
104,105,106,107,108,109,110,111 }; public static final int[] CHANNEL_NUMBER_2 = {116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127};
public static final int[] GROUP_ADDRESS_2 = {128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143};
public static final int[] CHANNEL_IDENTIFIER_2 = { 112,113,114,115 };
public static final int[] CHANNEL_NUMBER_2 = { 116,117,118,119,120,121,122,
123,124,125,126,127 };
public static final int[] GROUP_ADDRESS_2 = { 128,129,130,131,132,133,134,
135,136,137,138,139,140,141,142,143 };
private IBandIdentifier mIdentifierUpdate1; private IBandIdentifier mIdentifierUpdate1;
private IBandIdentifier mIdentifierUpdate2; private IBandIdentifier mIdentifierUpdate2;
public GroupMultiChannelGrant( BinaryMessage message, public GroupMultiChannelGrant(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append(getMessageStub());
sb.append( " CHAN1:" ); sb.append(" CHAN1:");
sb.append( getChannelIdentifier1() + "/" + getChannelNumber1() ); sb.append(getChannelIdentifier1() + "/" + getChannelNumber1());
sb.append( " GRP1:" ); sb.append(" GRP1:");
sb.append( getGroupAddress1() ); sb.append(getGroupAddress1());
if( hasChannelNumber2() ) if(hasChannelNumber2())
{ {
sb.append( " CHAN2:" ); sb.append(" CHAN2:");
sb.append( getChannelIdentifier2() + "/" + getChannelNumber2() ); sb.append(getChannelIdentifier2() + "/" + getChannelNumber2());
sb.append( " GRP2:" ); sb.append(" GRP2:");
sb.append( getGroupAddress2() ); sb.append(getGroupAddress2());
} }
return sb.toString(); return sb.toString();
} }
public int getChannelIdentifier1() public int getChannelIdentifier1()
{ {
return mMessage.getInt( CHANNEL_IDENTIFIER_1 ); return mMessage.getInt(CHANNEL_IDENTIFIER_1);
} }
public int getChannelNumber1() public int getChannelNumber1()
{ {
return mMessage.getInt( CHANNEL_NUMBER_1 ); return mMessage.getInt(CHANNEL_NUMBER_1);
} }
public String getChannel1() public String getChannel1()
{ {
return getChannelIdentifier1() + "-" + getChannelNumber1(); return getChannelIdentifier1() + "-" + getChannelNumber1();
} }
public String getGroupAddress1() public String getGroupAddress1()
{ {
return mMessage.getHex( GROUP_ADDRESS_1, 4 ); return mMessage.getHex(GROUP_ADDRESS_1, 4);
} }
public int getChannelIdentifier2() public int getChannelIdentifier2()
{ {
return mMessage.getInt( CHANNEL_IDENTIFIER_2 ); return mMessage.getInt(CHANNEL_IDENTIFIER_2);
} }
public int getChannelNumber2() public int getChannelNumber2()
{ {
return mMessage.getInt( CHANNEL_NUMBER_2 ); return mMessage.getInt(CHANNEL_NUMBER_2);
} }
public String getChannel2() public String getChannel2()
{ {
return getChannelIdentifier2() + "-" + getChannelNumber2(); return getChannelIdentifier2() + "-" + getChannelNumber2();
} }
public String getGroupAddress2() public String getGroupAddress2()
{ {
return mMessage.getHex( GROUP_ADDRESS_2, 4 ); return mMessage.getHex(GROUP_ADDRESS_2, 4);
} }
public boolean hasChannelNumber2() public boolean hasChannelNumber2()
{ {
return mMessage.getInt( CHANNEL_NUMBER_2 ) != return mMessage.getInt(CHANNEL_NUMBER_2) !=
mMessage.getInt( CHANNEL_NUMBER_1 ); mMessage.getInt(CHANNEL_NUMBER_1);
} }
@Override @Override
public String getFromID() public String getFromID()
{ {
@@ -112,59 +122,99 @@ public abstract class GroupMultiChannelGrant extends ChannelGrant
{ {
return getGroupAddress2(); return getGroupAddress2();
} }
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getChannelIdentifier1() )
{
mIdentifierUpdate1 = message;
}
if( hasChannelNumber2() && identifier == getChannelIdentifier2() ) @Override
{ public void setIdentifierMessage(int identifier, IBandIdentifier message)
mIdentifierUpdate2 = message; {
} if(identifier == getChannelIdentifier1())
{
mIdentifierUpdate1 = message;
}
if(hasChannelNumber2() && identifier == getChannelIdentifier2())
{
mIdentifierUpdate2 = message;
}
} }
@Override @Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers; int[] identifiers;
if( hasChannelNumber2() ) if(hasChannelNumber2())
{ {
identifiers = new int[ 2 ]; identifiers = new int[2];
identifiers[ 0 ] = getChannelIdentifier1(); identifiers[0] = getChannelIdentifier1();
identifiers[ 1 ] = getChannelIdentifier2(); identifiers[1] = getChannelIdentifier2();
} }
else else
{ {
identifiers = new int[ 1 ]; identifiers = new int[1];
identifiers[ 0 ] = getChannelIdentifier1(); identifiers[0] = getChannelIdentifier1();
} }
return identifiers; return identifiers;
} }
public long getDownlinkFrequency1() public long getDownlinkFrequency1()
{ {
return calculateDownlink( mIdentifierUpdate1, getChannelNumber1() ); if(mIdentifierUpdate1 != null)
{
return mIdentifierUpdate1.getDownlinkFrequency(getChannelNumber1());
}
return 0;
} }
public boolean isTDMAChannel1()
{
if(mIdentifierUpdate1 != null)
{
return mIdentifierUpdate1.isTDMA();
}
return false;
}
public long getUplinkFrequency1() public long getUplinkFrequency1()
{ {
return calculateUplink( mIdentifierUpdate1, getChannelNumber1() ); if(mIdentifierUpdate1 != null)
{
return mIdentifierUpdate1.getUplinkFrequency(getChannelNumber1());
}
return 0;
} }
public long getDownlinkFrequency2() public long getDownlinkFrequency2()
{ {
return calculateDownlink( mIdentifierUpdate2, getChannelNumber2() ); if(mIdentifierUpdate2 != null)
{
return mIdentifierUpdate2.getDownlinkFrequency(getChannelNumber2());
}
return 0;
} }
public boolean isTDMAChannel2()
{
if(mIdentifierUpdate2 != null)
{
return mIdentifierUpdate2.isTDMA();
}
return false;
}
public long getUplinkFrequency2() public long getUplinkFrequency2()
{ {
return calculateUplink( mIdentifierUpdate2, getChannelNumber2() ); if(mIdentifierUpdate2 != null)
{
return mIdentifierUpdate2.getUplinkFrequency(getChannelNumber2());
}
return 0;
} }
} }

View File

@@ -1,55 +1,70 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk; package module.decode.p25.message.tsbk;
import module.decode.p25.reference.DataUnitID;
import alias.Alias; import alias.Alias;
import alias.AliasList; import alias.AliasList;
import bits.BinaryMessage; import bits.BinaryMessage;
import module.decode.p25.reference.DataUnitID;
public abstract class UnitChannelGrant extends ChannelGrant public abstract class UnitChannelGrant extends ChannelGrant
{ {
public static final int[] TARGET_ADDRESS = { 96,97,98,99,100,101,102,103, public static final int[] TARGET_ADDRESS = {96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119 }; 111, 112, 113, 114, 115, 116, 117, 118, 119};
public static final int[] SOURCE_ADDRESS = {120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
public static final int[] SOURCE_ADDRESS = { 120,121,122,123,124,125,126, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143};
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public UnitChannelGrant(BinaryMessage message, DataUnitID duid, AliasList aliasList)
public UnitChannelGrant( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append(getMessageStub());
if( isEmergency() ) if(isEmergency())
{ {
sb.append( " EMERGENCY" ); sb.append(" EMERGENCY");
} }
sb.append( " FROM:" ); sb.append(" FROM:");
sb.append( getSourceAddress() ); sb.append(getSourceAddress());
sb.append( " TO:" ); sb.append(" TO:");
sb.append( getTargetAddress() ); sb.append(getTargetAddress());
return sb.toString(); return sb.toString();
} }
public String getTargetAddress() public String getTargetAddress()
{ {
return mMessage.getHex( TARGET_ADDRESS, 6 ); return mMessage.getHex(TARGET_ADDRESS, 6);
} }
public String getSourceAddress() public String getSourceAddress()
{ {
return mMessage.getHex( SOURCE_ADDRESS, 6 ); return mMessage.getHex(SOURCE_ADDRESS, 6);
} }
@Override @Override
public String getFromID() public String getFromID()
{ {
@@ -59,11 +74,11 @@ public abstract class UnitChannelGrant extends ChannelGrant
@Override @Override
public Alias getFromIDAlias() public Alias getFromIDAlias()
{ {
if( mAliasList != null ) if(mAliasList != null)
{ {
return mAliasList.getTalkgroupAlias( getFromID() ); return mAliasList.getTalkgroupAlias(getFromID());
} }
return null; return null;
} }

View File

@@ -1,34 +1,48 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.motorola; package module.decode.p25.message.tsbk.motorola;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import alias.AliasList;
import bits.BinaryMessage;
public class ControlChannelBaseStationIdentification extends MotorolaTSBKMessage public class ControlChannelBaseStationIdentification extends MotorolaTSBKMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
public static final int[] CHARACTER_1 = { 80,81,82,83,84,85 }; public static final int[] CHARACTER_1 = {80, 81, 82, 83, 84, 85};
public static final int[] CHARACTER_2 = { 86,87,88,89,90,91 }; public static final int[] CHARACTER_2 = {86, 87, 88, 89, 90, 91};
public static final int[] CHARACTER_3 = { 92,93,94,95,96,97 }; public static final int[] CHARACTER_3 = {92, 93, 94, 95, 96, 97};
public static final int[] CHARACTER_4 = { 98,99,100,101,102,103 }; public static final int[] CHARACTER_4 = {98, 99, 100, 101, 102, 103};
public static final int[] CHARACTER_5 = { 104,105,106,107,108,109 }; public static final int[] CHARACTER_5 = {104, 105, 106, 107, 108, 109};
public static final int[] CHARACTER_6 = { 110,111,112,113,114,115 }; public static final int[] CHARACTER_6 = {110, 111, 112, 113, 114, 115};
public static final int[] CHARACTER_7 = { 116,117,118,119,120,121 }; public static final int[] CHARACTER_7 = {116, 117, 118, 119, 120, 121};
public static final int[] CHARACTER_8 = { 122,123,124,125,126,127 }; public static final int[] CHARACTER_8 = {122, 123, 124, 125, 126, 127};
public static final int[] IDENTIFIER = { 128,129,130,131 }; public static final int[] IDENTIFIER = {128, 129, 130, 131};
public static final int[] CHANNEL = { 132,133,134,135,136,137,138,139,140, public static final int[] CHANNEL = {132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143};
141,142,143 };
private IBandIdentifier mIdentifierUpdate; private IBandIdentifier mIdentifierUpdate;
public ControlChannelBaseStationIdentification( BinaryMessage message, public ControlChannelBaseStationIdentification(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
@Override @Override
@@ -36,86 +50,96 @@ public class ControlChannelBaseStationIdentification extends MotorolaTSBKMessage
{ {
return MotorolaOpcode.CONTROL_CHANNEL_ID.getDescription(); return MotorolaOpcode.CONTROL_CHANNEL_ID.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " CHAN:" + getIdentifier() + "-" + getChannel() ); sb.append(getMessageStub());
sb.append( " CWID:" + getCWID() ); sb.append(" CHAN:" + getIdentifier() + "-" + getChannel());
sb.append( " DN:" + getDownlinkFrequency() ); sb.append(" CWID:" + getCWID());
sb.append( " UP:" + getUplinkFrequency() ); sb.append(" DN:" + getDownlinkFrequency());
sb.append(" UP:" + getUplinkFrequency());
return sb.toString(); return sb.toString();
} }
public String getCWID() public String getCWID()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getCharacter( CHARACTER_1 ) ); sb.append(getCharacter(CHARACTER_1));
sb.append( getCharacter( CHARACTER_2 ) ); sb.append(getCharacter(CHARACTER_2));
sb.append( getCharacter( CHARACTER_3 ) ); sb.append(getCharacter(CHARACTER_3));
sb.append( getCharacter( CHARACTER_4 ) ); sb.append(getCharacter(CHARACTER_4));
sb.append( getCharacter( CHARACTER_5 ) ); sb.append(getCharacter(CHARACTER_5));
sb.append( getCharacter( CHARACTER_6 ) ); sb.append(getCharacter(CHARACTER_6));
sb.append( getCharacter( CHARACTER_7 ) ); sb.append(getCharacter(CHARACTER_7));
sb.append( getCharacter( CHARACTER_8 ) ); sb.append(getCharacter(CHARACTER_8));
return sb.toString(); return sb.toString();
} }
private String getCharacter( int[] field ) private String getCharacter(int[] field)
{ {
int value = mMessage.getInt( field ); int value = mMessage.getInt(field);
if( value != 0 ) if(value != 0)
{ {
return String.valueOf( (char)( value + 43 ) ); return String.valueOf((char)(value + 43));
} }
return null; return null;
} }
public int getIdentifier() public int getIdentifier()
{ {
return mMessage.getInt( IDENTIFIER ); return mMessage.getInt(IDENTIFIER);
} }
public int getChannel() public int getChannel()
{ {
return mMessage.getInt( CHANNEL ); return mMessage.getInt(CHANNEL);
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdate, getChannel() ); if(mIdentifierUpdate != null)
{
mIdentifierUpdate.getUplinkFrequency(getChannel());
}
return 0;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdate, getChannel() ); if(mIdentifierUpdate != null)
{
mIdentifierUpdate.getDownlinkFrequency(getChannel());
}
return 0;
} }
@Override @Override
public void setIdentifierMessage( int identifier, IBandIdentifier message ) public void setIdentifierMessage(int identifier, IBandIdentifier message)
{ {
mIdentifierUpdate = message; mIdentifierUpdate = message;
} }
@Override @Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getIdentifier(); identifiers[0] = getIdentifier();
return identifiers; return identifiers;
} }
} }

View File

@@ -1,151 +1,187 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.motorola; package module.decode.p25.message.tsbk.motorola;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import alias.AliasList;
import bits.BinaryMessage;
public class PatchGroupVoiceChannelGrant extends MotorolaTSBKMessage public class PatchGroupVoiceChannelGrant extends MotorolaTSBKMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
/* Service Options */ /* Service Options */
public static final int EMERGENCY_FLAG = 80; public static final int EMERGENCY_FLAG = 80;
public static final int ENCRYPTED_CHANNEL_FLAG = 81; public static final int ENCRYPTED_CHANNEL_FLAG = 81;
public static final int DUPLEX_MODE = 82; public static final int DUPLEX_MODE = 82;
public static final int SESSION_MODE = 83; public static final int SESSION_MODE = 83;
public static final int[] PRIORITY = { 85,86,87 }; public static final int[] PRIORITY = {85, 86, 87};
public static final int[] IDENTIFIER = { 88,89,90,91 }; public static final int[] IDENTIFIER = {88, 89, 90, 91};
public static final int[] CHANNEL = { 92,93,94,95,96,97,98,99,100,101,102,103 }; public static final int[] CHANNEL = {92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103};
public static final int[] PATCH_GROUP_ADDRESS = { 104,105,106,107,108,109, public static final int[] PATCH_GROUP_ADDRESS = {104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
110,111,112,113,114,115,116,117,118,119 }; 117, 118, 119};
public static final int[] SOURCE_ADDRESS = { 120,121,122,123,124,125,126, public static final int[] SOURCE_ADDRESS = {120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 }; 134, 135, 136, 137, 138, 139, 140, 141, 142, 143};
private IBandIdentifier mIdentifierUpdate; private IBandIdentifier mIdentifierUpdate;
public PatchGroupVoiceChannelGrant( BinaryMessage message, DataUnitID duid, public PatchGroupVoiceChannelGrant(BinaryMessage message, DataUnitID duid, AliasList aliasList)
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
@Override public boolean isTDMAChannel()
{
if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.isTDMA();
}
return false;
}
@Override
public String getEventType() public String getEventType()
{ {
return MotorolaOpcode.PATCH_GROUP_CHANNEL_GRANT.getLabel(); return MotorolaOpcode.PATCH_GROUP_CHANNEL_GRANT.getLabel();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append(getMessageStub());
if( isEmergency() ) if(isEmergency())
{ {
sb.append( " EMERGENCY" ); sb.append(" EMERGENCY");
} }
sb.append( " PATCH GROUP:" );
sb.append( getPatchGroupAddress() );
sb.append( " FROM:" );
sb.append( getSourceAddress() );
sb.append( " PRI:" );
sb.append( getPriority() );
sb.append( " CHAN:" ); sb.append(" PATCH GROUP:");
sb.append( getChannelIdentifier() + "-" + getChannelNumber() ); sb.append(getPatchGroupAddress());
sb.append(" FROM:");
sb.append( " DN:" + getDownlinkFrequency() ); sb.append(getSourceAddress());
sb.append(" PRI:");
sb.append( " UP:" + getUplinkFrequency() ); sb.append(getPriority());
sb.append( " SESSION MODE:"); sb.append(" CHAN:");
sb.append( getSessionMode().name() ); sb.append(getChannelIdentifier() + "-" + getChannelNumber());
return sb.toString(); sb.append(" DN:" + getDownlinkFrequency());
sb.append(" UP:" + getUplinkFrequency());
sb.append(" SESSION MODE:");
sb.append(getSessionMode().name());
return sb.toString();
} }
public String getPatchGroupAddress() public String getPatchGroupAddress()
{ {
return mMessage.getHex( PATCH_GROUP_ADDRESS, 4 ); return mMessage.getHex(PATCH_GROUP_ADDRESS, 4);
} }
public String getSourceAddress() public String getSourceAddress()
{ {
return mMessage.getHex( SOURCE_ADDRESS, 6 ); return mMessage.getHex(SOURCE_ADDRESS, 6);
} }
public boolean isEmergency() public boolean isEmergency()
{ {
return mMessage.get( EMERGENCY_FLAG ); return mMessage.get(EMERGENCY_FLAG);
} }
public boolean isEncryptedChannel() public boolean isEncryptedChannel()
{ {
return mMessage.get( ENCRYPTED_CHANNEL_FLAG ); return mMessage.get(ENCRYPTED_CHANNEL_FLAG);
} }
public DuplexMode getDuplexMode() public DuplexMode getDuplexMode()
{ {
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF; return mMessage.get(DUPLEX_MODE) ? DuplexMode.FULL : DuplexMode.HALF;
} }
public SessionMode getSessionMode() public SessionMode getSessionMode()
{ {
return mMessage.get( SESSION_MODE ) ? return mMessage.get(SESSION_MODE) ?
SessionMode.CIRCUIT : SessionMode.PACKET; SessionMode.CIRCUIT : SessionMode.PACKET;
} }
/** /**
* 1 = Lowest, 4 = Default, 7 = Highest * 1 = Lowest, 4 = Default, 7 = Highest
*/ */
public int getPriority() public int getPriority()
{ {
return mMessage.getInt( PRIORITY ); return mMessage.getInt(PRIORITY);
} }
public int getChannelIdentifier() public int getChannelIdentifier()
{ {
return mMessage.getInt( IDENTIFIER ); return mMessage.getInt(IDENTIFIER);
} }
public int getChannelNumber() public int getChannelNumber()
{ {
return mMessage.getInt( CHANNEL ); return mMessage.getInt(CHANNEL);
} }
public String getChannel() public String getChannel()
{ {
return getChannelIdentifier() + "-" + getChannelNumber(); return getChannelIdentifier() + "-" + getChannelNumber();
} }
@Override @Override
public void setIdentifierMessage( int identifier, IBandIdentifier message ) public void setIdentifierMessage(int identifier, IBandIdentifier message)
{ {
mIdentifierUpdate = message; mIdentifierUpdate = message;
} }
@Override @Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 1 ]; int[] identifiers = new int[1];
identifiers[ 0 ] = getChannelIdentifier(); identifiers[0] = getChannelIdentifier();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getDownlinkFrequency(getChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdate, getChannelNumber() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getUplinkFrequency(getChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,146 +1,197 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.motorola; package module.decode.p25.message.tsbk.motorola;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import alias.AliasList;
import bits.BinaryMessage;
public class PatchGroupVoiceChannelGrantUpdate extends MotorolaTSBKMessage public class PatchGroupVoiceChannelGrantUpdate extends MotorolaTSBKMessage implements IdentifierReceiver
implements IdentifierReceiver
{ {
public static final int[] IDENTIFIER_1 = { 80,81,82,83 }; public static final int[] IDENTIFIER_1 = {80, 81, 82, 83};
public static final int[] CHANNEL_1 = { 84,85,86,87,88,89,90,91,92,93,94, public static final int[] CHANNEL_1 = {84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95};
95 }; public static final int[] PATCH_GROUP_ADDRESS_1 = {96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111};
public static final int[] PATCH_GROUP_ADDRESS_1 = { 96,97,98,99,100,101,102, public static final int[] IDENTIFIER_2 = {112, 113, 114, 115};
103,104,105,106,107,108,109,110,111 }; public static final int[] CHANNEL_2 = {116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127};
public static final int[] IDENTIFIER_2 = { 112,113,114,115 }; public static final int[] PATCH_GROUP_ADDRESS_2 = {128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143};
public static final int[] CHANNEL_2 = { 116,117,118,119,120,121,122,123,
124,125,126,127 };
public static final int[] PATCH_GROUP_ADDRESS_2 = { 128,129,130,131,132,133,
134,135,136,137,138,139,140,141,142,143 };
private IBandIdentifier mIdentifierUpdate1; private IBandIdentifier mIdentifierUpdate1;
private IBandIdentifier mIdentifierUpdate2; private IBandIdentifier mIdentifierUpdate2;
public PatchGroupVoiceChannelGrantUpdate( BinaryMessage message, public PatchGroupVoiceChannelGrantUpdate(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid, AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
@Override @Override
public String getEventType() public String getEventType()
{ {
return MotorolaOpcode.PATCH_GROUP_CHANNEL_GRANT_UPDATE.getLabel(); return MotorolaOpcode.PATCH_GROUP_CHANNEL_GRANT_UPDATE.getLabel();
} }
@Override @Override
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append(getMessageStub());
sb.append( " PATCH GRP1:" );
sb.append( getPatchGroupAddress1() );
sb.append( " GRP2:" );
sb.append( getPatchGroupAddress2() );
sb.append( " CHAN 1:" ); sb.append(" PATCH GRP1:");
sb.append( getChannel1() ); sb.append(getPatchGroupAddress1());
sb.append( " DN:" + getDownlinkFrequency1() ); sb.append(" GRP2:");
sb.append(getPatchGroupAddress2());
sb.append( " CHAN 2:" );
sb.append( getChannel2() ); sb.append(" CHAN 1:");
sb.append( " DN:" + getDownlinkFrequency2() ); sb.append(getChannel1());
sb.append(" DN:" + getDownlinkFrequency1());
return sb.toString();
sb.append(" CHAN 2:");
sb.append(getChannel2());
sb.append(" DN:" + getDownlinkFrequency2());
return sb.toString();
} }
public String getPatchGroupAddress1() public String getPatchGroupAddress1()
{ {
return mMessage.getHex( PATCH_GROUP_ADDRESS_1, 4 ); return mMessage.getHex(PATCH_GROUP_ADDRESS_1, 4);
} }
public String getPatchGroupAddress2() public String getPatchGroupAddress2()
{ {
return mMessage.getHex( PATCH_GROUP_ADDRESS_2, 4 ); return mMessage.getHex(PATCH_GROUP_ADDRESS_2, 4);
} }
public int getChannelIdentifier1() public int getChannelIdentifier1()
{ {
return mMessage.getInt( IDENTIFIER_1 ); return mMessage.getInt(IDENTIFIER_1);
} }
public int getChannelNumber1() public int getChannelNumber1()
{ {
return mMessage.getInt( CHANNEL_1 ); return mMessage.getInt(CHANNEL_1);
} }
public String getChannel1() public String getChannel1()
{ {
return getChannelIdentifier1() + "-" + getChannelNumber1(); return getChannelIdentifier1() + "-" + getChannelNumber1();
} }
public int getChannelIdentifier2() public int getChannelIdentifier2()
{ {
return mMessage.getInt( IDENTIFIER_2 ); return mMessage.getInt(IDENTIFIER_2);
} }
public int getChannelNumber2() public int getChannelNumber2()
{ {
return mMessage.getInt( CHANNEL_2 ); return mMessage.getInt(CHANNEL_2);
} }
public String getChannel2() public String getChannel2()
{ {
return getChannelIdentifier2() + "-" + getChannelNumber2(); return getChannelIdentifier2() + "-" + getChannelNumber2();
} }
@Override @Override
public void setIdentifierMessage( int identifier, IBandIdentifier message ) public void setIdentifierMessage(int identifier, IBandIdentifier message)
{ {
if( identifier == getChannelIdentifier1() ) if(identifier == getChannelIdentifier1())
{ {
mIdentifierUpdate1 = message; mIdentifierUpdate1 = message;
} }
if( identifier == getChannelIdentifier2() ) if(identifier == getChannelIdentifier2())
{ {
mIdentifierUpdate2 = message; mIdentifierUpdate2 = message;
} }
} }
@Override @Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getChannelIdentifier1(); identifiers[0] = getChannelIdentifier1();
identifiers[ 1 ] = getChannelIdentifier2(); identifiers[1] = getChannelIdentifier2();
return identifiers; return identifiers;
} }
public long getDownlinkFrequency1() public long getDownlinkFrequency1()
{ {
return calculateDownlink( mIdentifierUpdate1, getChannelNumber1() ); if(mIdentifierUpdate1 != null)
{
return mIdentifierUpdate1.getDownlinkFrequency(getChannelNumber1());
}
return 0;
} }
public boolean isTDMAChannel1()
{
if(mIdentifierUpdate1 != null)
{
return mIdentifierUpdate1.isTDMA();
}
return false;
}
public long getUplinkFrequency1() public long getUplinkFrequency1()
{ {
return calculateUplink( mIdentifierUpdate1, getChannelNumber1() ); if(mIdentifierUpdate1 != null)
{
return mIdentifierUpdate1.getUplinkFrequency(getChannelNumber1());
}
return 0;
} }
public long getDownlinkFrequency2() public long getDownlinkFrequency2()
{ {
return calculateDownlink( mIdentifierUpdate2, getChannelNumber2() ); if(mIdentifierUpdate2 != null)
{
return mIdentifierUpdate2.getDownlinkFrequency(getChannelNumber2());
}
return 0;
} }
public boolean isTDMAChannel2()
{
if(mIdentifierUpdate2 != null)
{
return mIdentifierUpdate2.isTDMA();
}
return false;
}
public long getUplinkFrequency2() public long getUplinkFrequency2()
{ {
return calculateUplink( mIdentifierUpdate2, getChannelNumber2() ); if(mIdentifierUpdate2 != null)
{
return mIdentifierUpdate2.getUplinkFrequency(getChannelNumber2());
}
return 0;
} }
} }

View File

@@ -1,40 +1,51 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.osp.control; package module.decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IAdjacentSite; import module.decode.p25.message.IAdjacentSite;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.TSBKMessage; import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class AdjacentStatusBroadcast extends TSBKMessage public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierReceiver, IAdjacentSite
implements IdentifierReceiver, IAdjacentSite
{ {
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85, public static final int[] LOCATION_REGISTRATION_AREA = {80, 81, 82, 83, 84, 85, 86, 87};
86,87 };
public static final int CONVENTIONAL_CHANNEL_FLAG = 88; public static final int CONVENTIONAL_CHANNEL_FLAG = 88;
public static final int SITE_FAILURE_CONDITION_FLAG = 89; public static final int SITE_FAILURE_CONDITION_FLAG = 89;
public static final int VALID_FLAG = 90; public static final int VALID_FLAG = 90;
public static final int ACTIVE_NETWORK_CONNECTION_FLAG = 91; public static final int ACTIVE_NETWORK_CONNECTION_FLAG = 91;
public static final int[] SYSTEM_ID = { 92,93,94,95,96,97,98,99,100,101, public static final int[] SYSTEM_ID = {92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103};
102,103 }; public static final int[] RFSS_ID = {104, 105, 106, 107, 108, 109, 110, 111};
public static final int[] RFSS_ID = { 104,105,106,107,108,109,110,111 }; public static final int[] SITE_ID = {112, 113, 114, 115, 116, 117, 118, 119};
public static final int[] SITE_ID = { 112,113,114,115,116,117,118,119 }; public static final int[] IDENTIFIER = {120, 121, 122, 123};
public static final int[] IDENTIFIER = { 120,121,122,123 }; public static final int[] CHANNEL = {124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135};
public static final int[] CHANNEL = { 124,125,126,127,128,129,130,131,132, public static final int[] SYSTEM_SERVICE_CLASS = {136, 137, 138, 139, 140, 141, 142, 143};
133,134,135 };
public static final int[] SYSTEM_SERVICE_CLASS = { 136,137,138,139,140,141,
142,143 };
private IBandIdentifier mIdentifierUpdate; private IBandIdentifier mIdentifierUpdate;
public AdjacentStatusBroadcast( BinaryMessage message, public AdjacentStatusBroadcast(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
@Override @Override
@@ -42,154 +53,164 @@ public class AdjacentStatusBroadcast extends TSBKMessage
{ {
return Opcode.ADJACENT_STATUS_BROADCAST.getDescription(); return Opcode.ADJACENT_STATUS_BROADCAST.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLRA() );
sb.append( " SYS:" + getSystemID() ); sb.append(getMessageStub());
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() ); sb.append(" LRA:" + getLRA());
sb.append( " CHAN:" + getIdentifier() + "-" + getChannel() );
sb.append( " DN:" + getDownlinkFrequency() ); sb.append(" SYS:" + getSystemID());
sb.append( " UP:" + getUplinkFrequency() ); sb.append(" SITE:" + getRFSS() + "-" + getSiteID());
if( isConventionalChannel() ) sb.append(" CHAN:" + getIdentifier() + "-" + getChannel());
sb.append(" DN:" + getDownlinkFrequency());
sb.append(" UP:" + getUplinkFrequency());
if(isConventionalChannel())
{ {
sb.append( " CONVENTIONAL" ); sb.append(" CONVENTIONAL");
} }
if( isSiteFailureCondition() ) if(isSiteFailureCondition())
{ {
sb.append( " FAILURE-CONDITION" ); sb.append(" FAILURE-CONDITION");
} }
if( isValidSiteInformation() ) if(isValidSiteInformation())
{ {
sb.append( " VALID-INFO" ); sb.append(" VALID-INFO");
} }
if( hasActiveNetworkConnection() ) if(hasActiveNetworkConnection())
{ {
sb.append( " ACTIVE-NETWORK-CONN" ); sb.append(" ACTIVE-NETWORK-CONN");
} }
sb.append( getSystemServiceClass() ); sb.append(getSystemServiceClass());
return sb.toString(); return sb.toString();
} }
@Override @Override
public String getDownlinkChannel() public String getDownlinkChannel()
{
return getIdentifier() + "-" + getChannel();
}
@Override
public String getUplinkChannel()
{
return getIdentifier() + "-" + getChannel();
}
public String getLRA()
{ {
return mMessage.getHex( LOCATION_REGISTRATION_AREA, 2 ); return getIdentifier() + "-" + getChannel();
} }
@Override
public String getUplinkChannel()
{
return getIdentifier() + "-" + getChannel();
}
public String getLRA()
{
return mMessage.getHex(LOCATION_REGISTRATION_AREA, 2);
}
public boolean isConventionalChannel() public boolean isConventionalChannel()
{ {
return mMessage.get( CONVENTIONAL_CHANNEL_FLAG ); return mMessage.get(CONVENTIONAL_CHANNEL_FLAG);
} }
public boolean isSiteFailureCondition() public boolean isSiteFailureCondition()
{ {
return mMessage.get( SITE_FAILURE_CONDITION_FLAG ); return mMessage.get(SITE_FAILURE_CONDITION_FLAG);
} }
public boolean isValidSiteInformation() public boolean isValidSiteInformation()
{ {
return mMessage.get( VALID_FLAG ); return mMessage.get(VALID_FLAG);
} }
public boolean hasActiveNetworkConnection() public boolean hasActiveNetworkConnection()
{ {
return mMessage.get( ACTIVE_NETWORK_CONNECTION_FLAG ); return mMessage.get(ACTIVE_NETWORK_CONNECTION_FLAG);
} }
public String getUniqueID() public String getUniqueID()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getSystemID() ); sb.append(getSystemID());
sb.append( ":" ); sb.append(":");
sb.append( getRFSS() ); sb.append(getRFSS());
sb.append( ":" ); sb.append(":");
sb.append( getSiteID() ); sb.append(getSiteID());
return sb.toString(); return sb.toString();
} }
public String getSystemID() public String getSystemID()
{ {
return mMessage.getHex( SYSTEM_ID, 3 ); return mMessage.getHex(SYSTEM_ID, 3);
} }
public String getRFSS() public String getRFSS()
{ {
return mMessage.getHex( RFSS_ID, 2 ); return mMessage.getHex(RFSS_ID, 2);
} }
public String getSiteID() public String getSiteID()
{ {
return mMessage.getHex( SITE_ID, 2 ); return mMessage.getHex(SITE_ID, 2);
} }
public int getChannel() public int getChannel()
{ {
return mMessage.getInt( CHANNEL ); return mMessage.getInt(CHANNEL);
} }
public int getIdentifier() public int getIdentifier()
{ {
return mMessage.getInt( IDENTIFIER ); return mMessage.getInt(IDENTIFIER);
} }
public String getSystemServiceClass() public String getSystemServiceClass()
{ {
return SystemService.toString( mMessage.getInt( SYSTEM_SERVICE_CLASS ) ); return SystemService.toString(mMessage.getInt(SYSTEM_SERVICE_CLASS));
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdate, getChannel() ); if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getDownlinkFrequency(getChannel());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdate, getChannel() ); if(mIdentifierUpdate != null)
} {
return mIdentifierUpdate.getUplinkFrequency(getChannel());
}
@Override return 0;
public void setIdentifierMessage( int identifier, IBandIdentifier message ) }
{
/* we're only expecting 1 identifier, so use whatever is received */
mIdentifierUpdate = message; @Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
/* we're only expecting 1 identifier, so use whatever is received */
mIdentifierUpdate = message;
}
public int[] getIdentifiers()
{
int[] idens = new int[1];
idens[0] = getIdentifier();
return idens;
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 1 ];
idens[ 0 ] = getIdentifier();
return idens;
}
} }

View File

@@ -1,3 +1,21 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.osp.control; package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
@@ -6,8 +24,7 @@ import module.decode.p25.reference.DataUnitID;
import alias.AliasList; import alias.AliasList;
import bits.BinaryMessage; import bits.BinaryMessage;
public abstract class IdentifierUpdate extends TSBKMessage public abstract class IdentifierUpdate extends TSBKMessage implements IBandIdentifier
implements IBandIdentifier
{ {
public static final int[] IDENTIFIER = { 80,81,82,83 }; public static final int[] IDENTIFIER = { 80,81,82,83 };
@@ -45,4 +62,22 @@ public abstract class IdentifierUpdate extends TSBKMessage
@Override @Override
public abstract long getTransmitOffset(); public abstract long getTransmitOffset();
@Override
public long getDownlinkFrequency(int channelNumber)
{
return getBaseFrequency() + ( channelNumber * getChannelSpacing() );
}
@Override
public long getUplinkFrequency(int channelNumber)
{
return getDownlinkFrequency(channelNumber) + getTransmitOffset();
}
@Override
public boolean isTDMA()
{
return false;
}
} }

View File

@@ -31,17 +31,21 @@ public class IdentifierUpdateNonVUHF extends IdentifierUpdate
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append( getMessageStub() );
sb.append(toString());
sb.append( " IDEN:" + getIdentifier() ); return sb.toString();
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append( " ID:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() ); sb.append( " BASE:" + getBaseFrequency() );
sb.append( " BANDWIDTH:" + getBandwidth() );
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() ); sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() ); sb.append( " OFFSET:" + getTransmitOffset() );
return sb.toString(); return sb.toString();
} }

View File

@@ -30,18 +30,26 @@ public class IdentifierUpdateTDMA extends IdentifierUpdate
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append( getMessageStub() );
sb.append(toString());
sb.append( " IDEN:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() );
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() );
sb.append( " TYPE:" + getChannelType().toString() );
return sb.toString(); return sb.toString();
} }
public ChannelType getChannelType() public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append( " ID:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() );
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() );
sb.append( " TYPE:" + getChannelType().toString() );
return sb.toString();
}
public ChannelType getChannelType()
{ {
return ChannelType.fromValue( mMessage.getInt( CHANNEL_TYPE) ); return ChannelType.fromValue( mMessage.getInt( CHANNEL_TYPE) );
} }
@@ -72,7 +80,26 @@ public class IdentifierUpdateTDMA extends IdentifierUpdate
return -offset; return -offset;
} }
} }
@Override
public long getDownlinkFrequency(int channelNumber)
{
if(isTDMA())
{
return getBaseFrequency() + ( (channelNumber / getChannelType().getSlotsPerCarrier()) * getChannelSpacing() );
}
else
{
return super.getDownlinkFrequency(channelNumber);
}
}
@Override
public boolean isTDMA()
{
return getChannelType().getAccessType() == AccessType.TDMA;
}
public enum ChannelType public enum ChannelType
{ {
TYPE_0( AccessType.FDMA, 12500, 1, Vocoder.HALF_RATE ), TYPE_0( AccessType.FDMA, 12500, 1, Vocoder.HALF_RATE ),
@@ -109,7 +136,7 @@ public class IdentifierUpdateTDMA extends IdentifierUpdate
} }
sb.append( mAccessType.name() ); sb.append( mAccessType.name() );
sb.append( " BW:" + mBandwidth ); sb.append( " BANDWIDTH:" + mBandwidth );
sb.append( " SLOT/CARRIER:" + mSlotsPerCarrier ); sb.append( " SLOT/CARRIER:" + mSlotsPerCarrier );
sb.append( " VOCODER:" + mVocoder.name() ); sb.append( " VOCODER:" + mVocoder.name() );

View File

@@ -32,17 +32,21 @@ public class IdentifierUpdateVUHF extends IdentifierUpdate
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append( getMessageStub() );
sb.append(toString());
sb.append( " IDEN:" + getIdentifier() ); return sb.toString();
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append( " ID:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() ); sb.append( " BASE:" + getBaseFrequency() );
sb.append( " BANDWIDTH:" + getBandwidth() );
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() ); sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() ); sb.append( " OFFSET:" + getTransmitOffset() );
return sb.toString(); return sb.toString();
} }

View File

@@ -1,35 +1,46 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.osp.control; package module.decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.TSBKMessage; import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.P25NetworkCallsign; import module.decode.p25.reference.P25NetworkCallsign;
import alias.AliasList;
import bits.BinaryMessage;
public class NetworkStatusBroadcast extends TSBKMessage implements IdentifierReceiver public class NetworkStatusBroadcast extends TSBKMessage implements IdentifierReceiver
{ {
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85, public static final int[] LOCATION_REGISTRATION_AREA = {80, 81, 82, 83, 84, 85, 86, 87};
86,87 }; public static final int[] WACN = {88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107};
public static final int[] WACN = { 88,89,90,91,92,93,94,95,96,97,98,99,100, public static final int[] SYSTEM_ID = {108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
101,102,103,104,105,106,107 }; public static final int[] IDENTIFIER = {120, 121, 122, 123};
public static final int[] SYSTEM_ID = { 108,109,110,111,112,113,114,115,116, public static final int[] CHANNEL = {124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135};
117,118,119 }; public static final int[] SYSTEM_SERVICE_CLASS = {136, 137, 138, 139, 140, 141, 142, 143};
public static final int[] IDENTIFIER = { 120,121,122,123 };
public static final int[] CHANNEL = { 124,125,126,127,128,129,130,131,132,
133,134,135 };
public static final int[] SYSTEM_SERVICE_CLASS = { 136,137,138,139,140,141,
142,143 };
private IBandIdentifier mIdentifierUpdate; private IBandIdentifier mIdentifierUpdate;
public NetworkStatusBroadcast( BinaryMessage message, public NetworkStatusBroadcast(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
@Override @Override
@@ -37,90 +48,100 @@ public class NetworkStatusBroadcast extends TSBKMessage implements IdentifierRec
{ {
return Opcode.NETWORK_STATUS_BROADCAST.getDescription(); return Opcode.NETWORK_STATUS_BROADCAST.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() ); sb.append(getMessageStub());
sb.append( " WACN:" + getWACN() ); sb.append(" LRA:" + getLocationRegistrationArea());
sb.append( " SYS:" + getSystemID() ); sb.append(" WACN:" + getWACN());
sb.append( " CTRL CHAN:" + getIdentifier() + "-" + getChannel() ); sb.append(" SYS:" + getSystemID());
sb.append( " DN:" + getDownlinkFrequency() ); sb.append(" CTRL CHAN:" + getIdentifier() + "-" + getChannel());
sb.append( " UP:" + getUplinkFrequency() ); sb.append(" DN:" + getDownlinkFrequency());
sb.append( " SYS SVC CLASS:" + sb.append(" UP:" + getUplinkFrequency());
SystemService.toString( getSystemServiceClass() ) );
sb.append(" SYS SVC CLASS:" +
SystemService.toString(getSystemServiceClass()));
return sb.toString(); return sb.toString();
} }
public String getLocationRegistrationArea() public String getLocationRegistrationArea()
{ {
return mMessage.getHex( LOCATION_REGISTRATION_AREA, 2 ); return mMessage.getHex(LOCATION_REGISTRATION_AREA, 2);
} }
public String getWACN() public String getWACN()
{ {
return mMessage.getHex( WACN, 5 ); return mMessage.getHex(WACN, 5);
} }
public String getSystemID() public String getSystemID()
{ {
return mMessage.getHex( SYSTEM_ID, 3 ); return mMessage.getHex(SYSTEM_ID, 3);
}
public String getNetworkCallsign()
{
return P25NetworkCallsign.getCallsign(mMessage.getInt(WACN),
mMessage.getInt(SYSTEM_ID));
} }
public String getNetworkCallsign()
{
return P25NetworkCallsign.getCallsign( mMessage.getInt( WACN ),
mMessage.getInt( SYSTEM_ID ) );
}
public int getIdentifier() public int getIdentifier()
{ {
return mMessage.getInt( IDENTIFIER ); return mMessage.getInt(IDENTIFIER);
} }
public int getChannel() public int getChannel()
{ {
return mMessage.getInt( CHANNEL ); return mMessage.getInt(CHANNEL);
} }
public int getSystemServiceClass() public int getSystemServiceClass()
{ {
return mMessage.getInt( SYSTEM_SERVICE_CLASS ); return mMessage.getInt(SYSTEM_SERVICE_CLASS);
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdate, getChannel() ); if(mIdentifierUpdate != null)
} {
return mIdentifierUpdate.getDownlinkFrequency(getChannel());
public long getUplinkFrequency() }
{
return calculateUplink( mIdentifierUpdate, getChannel() ); return 0;
} }
@Override public long getUplinkFrequency()
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
/* we're only expecting 1 identifier, so use whatever is received */ if(mIdentifierUpdate != null)
mIdentifierUpdate = message; {
return mIdentifierUpdate.getUplinkFrequency(getChannel());
}
return 0;
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
/* we're only expecting 1 identifier, so use whatever is received */
mIdentifierUpdate = message;
}
public int[] getIdentifiers()
{
int[] idens = new int[1];
idens[0] = getIdentifier();
return idens;
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 1 ];
idens[ 0 ] = getIdentifier();
return idens;
}
} }

View File

@@ -1,35 +1,47 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.osp.control; package module.decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.TSBKMessage; import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class RFSSStatusBroadcast extends TSBKMessage implements IdentifierReceiver public class RFSSStatusBroadcast extends TSBKMessage implements IdentifierReceiver
{ {
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85, public static final int[] LOCATION_REGISTRATION_AREA = {80, 81, 82, 83, 84, 85, 86, 87};
86,87 };
public static final int ACTIVE_NETWORK_CONNECTION_FLAG = 91; public static final int ACTIVE_NETWORK_CONNECTION_FLAG = 91;
public static final int[] SYSTEM_ID = { 92,93,94,95,96,97,98,99,100,101, public static final int[] SYSTEM_ID = {92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103};
102,103 }; public static final int[] RFSS_ID = {104, 105, 106, 107, 108, 109, 110, 111};
public static final int[] RFSS_ID = { 104,105,106,107,108,109,110,111 }; public static final int[] SITE_ID = {112, 113, 114, 115, 116, 117, 118, 119};
public static final int[] SITE_ID = { 112,113,114,115,116,117,118,119 }; public static final int[] IDENTIFIER = {120, 121, 122, 123};
public static final int[] IDENTIFIER = { 120,121,122,123 }; public static final int[] CHANNEL = {124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135};
public static final int[] CHANNEL = { 124,125,126,127,128,129,130,131,132, public static final int[] SYSTEM_SERVICE_CLASS = {136, 137, 138, 139, 140, 141, 142, 143};
133,134,135 };
public static final int[] SYSTEM_SERVICE_CLASS = { 136,137,138,139,140,141,
142,143 };
private IBandIdentifier mIdentifierUpdate; private IBandIdentifier mIdentifierUpdate;
public RFSSStatusBroadcast( BinaryMessage message, public RFSSStatusBroadcast(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
@Override @Override
@@ -37,100 +49,110 @@ public class RFSSStatusBroadcast extends TSBKMessage implements IdentifierReceiv
{ {
return Opcode.RFSS_STATUS_BROADCAST.getDescription(); return Opcode.RFSS_STATUS_BROADCAST.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SYSID:" + getSystemID() ); sb.append(getMessageStub());
sb.append( " RFSS:" + getRFSubsystemID() ); sb.append(" LRA:" + getLocationRegistrationArea());
sb.append( " SITE:" + getSiteID() );
sb.append( " CHAN:" + getIdentifier() + "-" + getChannel() );
sb.append( " DN:" + getDownlinkFrequency() );
sb.append( " UP:" + getUplinkFrequency() );
if( hasActiveNetworkConnection() ) sb.append(" SYSID:" + getSystemID());
sb.append(" RFSS:" + getRFSubsystemID());
sb.append(" SITE:" + getSiteID());
sb.append(" CHAN:" + getIdentifier() + "-" + getChannel());
sb.append(" DN:" + getDownlinkFrequency());
sb.append(" UP:" + getUplinkFrequency());
if(hasActiveNetworkConnection())
{ {
sb.append( " ACTIVE-NETWORK-CONN" ); sb.append(" ACTIVE-NETWORK-CONN");
} }
sb.append( SystemService.toString( getSystemServiceClass() ) ); sb.append(SystemService.toString(getSystemServiceClass()));
return sb.toString(); return sb.toString();
} }
public String getLocationRegistrationArea() public String getLocationRegistrationArea()
{ {
return mMessage.getHex( LOCATION_REGISTRATION_AREA, 2 ); return mMessage.getHex(LOCATION_REGISTRATION_AREA, 2);
} }
public boolean hasActiveNetworkConnection() public boolean hasActiveNetworkConnection()
{ {
return mMessage.get( ACTIVE_NETWORK_CONNECTION_FLAG ); return mMessage.get(ACTIVE_NETWORK_CONNECTION_FLAG);
} }
public String getSystemID() public String getSystemID()
{ {
return mMessage.getHex( SYSTEM_ID, 3 ); return mMessage.getHex(SYSTEM_ID, 3);
} }
public String getRFSubsystemID() public String getRFSubsystemID()
{ {
return mMessage.getHex( RFSS_ID, 2 ); return mMessage.getHex(RFSS_ID, 2);
} }
public String getSiteID() public String getSiteID()
{ {
return mMessage.getHex( SITE_ID, 2 ); return mMessage.getHex(SITE_ID, 2);
} }
public int getIdentifier() public int getIdentifier()
{ {
return mMessage.getInt( IDENTIFIER ); return mMessage.getInt(IDENTIFIER);
}
public int getChannel()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
public long getDownlinkFrequency()
{
return calculateDownlink( mIdentifierUpdate, getChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mIdentifierUpdate, getChannel() );
} }
@Override public int getChannel()
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{ {
/* we're only expecting 1 identifier, so use whatever is received */ return mMessage.getInt(CHANNEL);
mIdentifierUpdate = message; }
public int getSystemServiceClass()
{
return mMessage.getInt(SYSTEM_SERVICE_CLASS);
}
public long getDownlinkFrequency()
{
if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getDownlinkFrequency(getChannel());
}
return 0;
}
public long getUplinkFrequency()
{
if(mIdentifierUpdate != null)
{
return mIdentifierUpdate.getUplinkFrequency(getChannel());
}
return 0;
}
@Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
/* we're only expecting 1 identifier, so use whatever is received */
mIdentifierUpdate = message;
}
public int[] getIdentifiers()
{
int[] idens = new int[1];
idens[0] = getIdentifier();
return idens;
} }
public int[] getIdentifiers()
{
int[] idens = new int[ 1 ];
idens[ 0 ] = getIdentifier();
return idens;
}
} }

View File

@@ -1,44 +1,50 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.osp.control; package module.decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.TSBKMessage; import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import org.slf4j.Logger; public class SecondaryControlChannelBroadcast extends TSBKMessage implements IdentifierReceiver, Comparable<SecondaryControlChannelBroadcast>
import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BinaryMessage;
public class SecondaryControlChannelBroadcast extends TSBKMessage
implements IdentifierReceiver, Comparable<SecondaryControlChannelBroadcast>
{ {
private final static Logger mLog = public static final int[] RFSS_ID = {80, 81, 82, 83, 84, 85, 86, 87};
LoggerFactory.getLogger( SecondaryControlChannelBroadcast.class ); public static final int[] SITE_ID = {88, 89, 90, 91, 92, 93, 94, 95};
public static final int[] IDENTIFIER_1 = {96, 97, 98, 99};
public static final int[] CHANNEL_1 = {100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111};
public static final int[] SYSTEM_SERVICE_CLASS_1 = {112, 113, 114, 115, 116, 117, 118, 119};
public static final int[] IDENTIFIER_2 = {120, 121, 122, 123};
public static final int[] CHANNEL_2 = {124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135};
public static final int[] SYSTEM_SERVICE_CLASS_2 = {136, 137, 138, 139, 140, 141, 142, 143};
public static final int[] RFSS_ID = { 80,81,82,83,84,85,86,87 };
public static final int[] SITE_ID = { 88,89,90,91,92,93,94,95 };
public static final int[] IDENTIFIER_1 = { 96,97,98,99 };
public static final int[] CHANNEL_1 = { 100,101,102,103,104,105,106,107,108,
109,110,111 };
public static final int[] SYSTEM_SERVICE_CLASS_1 = { 112,113,114,115,116,
117,118,119 };
public static final int[] IDENTIFIER_2 = { 120,121,122,123 };
public static final int[] CHANNEL_2 = { 124,125,126,127,128,129,130,131,132,
133,134,135 };
public static final int[] SYSTEM_SERVICE_CLASS_2 = { 136,137,138,139,140,
141,142,143 };
private IBandIdentifier mIdentifierUpdate1; private IBandIdentifier mIdentifierUpdate1;
private IBandIdentifier mIdentifierUpdate2; private IBandIdentifier mIdentifierUpdate2;
public SecondaryControlChannelBroadcast( BinaryMessage message, public SecondaryControlChannelBroadcast(BinaryMessage message,
DataUnitID duid, DataUnitID duid,
AliasList aliasList ) AliasList aliasList)
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
@Override @Override
@@ -46,162 +52,215 @@ public class SecondaryControlChannelBroadcast extends TSBKMessage
{ {
return Opcode.SECONDARY_CONTROL_CHANNEL_BROADCAST.getDescription(); return Opcode.SECONDARY_CONTROL_CHANNEL_BROADCAST.getDescription();
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() );
sb.append( " CHAN1:" + getIdentifier1() + "-" + getChannel1() );
sb.append( " DN1:" + getDownlinkFrequency1() );
sb.append( " UP1:" + getUplinkFrequency1() );
sb.append( " SVC1:" +
SystemService.toString( getSystemServiceClass1() ) );
if( hasChannel2() ) sb.append(getMessageStub());
sb.append(" SITE:" + getRFSS() + "-" + getSiteID());
sb.append(" CHAN1:" + getIdentifier1() + "-" + getChannel1());
sb.append(" DN1:" + getDownlinkFrequency1());
sb.append(" UP1:" + getUplinkFrequency1());
sb.append(" SVC1:" + SystemService.toString(getSystemServiceClass1()));
if(hasChannel2())
{ {
sb.append( " CHAN2:" + getIdentifier2() + "-" + getChannel2() ); sb.append(" CHAN2:" + getIdentifier2() + "-" + getChannel2());
sb.append( " DN2:" + getDownlinkFrequency2() ); sb.append(" DN2:" + getDownlinkFrequency2());
sb.append( " UP2:" + getUplinkFrequency2() ); sb.append(" UP2:" + getUplinkFrequency2());
sb.append( " SVC2:" + sb.append(" SVC2:" + SystemService.toString(getSystemServiceClass2()));
SystemService.toString( getSystemServiceClass2() ) );
} }
return sb.toString(); return sb.toString();
} }
public String getRFSS() public String getRFSS()
{ {
return mMessage.getHex( RFSS_ID, 2 ); return mMessage.getHex(RFSS_ID, 2);
} }
public String getSiteID() public String getSiteID()
{ {
return mMessage.getHex( SITE_ID, 2 ); return mMessage.getHex(SITE_ID, 2);
} }
public int getIdentifier1() public int getIdentifier1()
{ {
return mMessage.getInt( IDENTIFIER_1 ); return mMessage.getInt(IDENTIFIER_1);
} }
public int getChannel1() public int getChannel1()
{ {
return mMessage.getInt( CHANNEL_1 ); return mMessage.getInt(CHANNEL_1);
} }
public int getSystemServiceClass1() public int getSystemServiceClass1()
{ {
return mMessage.getInt( SYSTEM_SERVICE_CLASS_1 ); return mMessage.getInt(SYSTEM_SERVICE_CLASS_1);
} }
public int getIdentifier2() public int getIdentifier2()
{ {
return mMessage.getInt( IDENTIFIER_2 ); return mMessage.getInt(IDENTIFIER_2);
} }
public int getChannel2() public int getChannel2()
{ {
return mMessage.getInt( CHANNEL_2 ); return mMessage.getInt(CHANNEL_2);
} }
public int getSystemServiceClass2() public int getSystemServiceClass2()
{ {
return mMessage.getInt( SYSTEM_SERVICE_CLASS_2 ); return mMessage.getInt(SYSTEM_SERVICE_CLASS_2);
} }
public boolean hasChannel2() public boolean hasChannel2()
{ {
return getSystemServiceClass2() != 0; return getSystemServiceClass2() != 0;
} }
public long getDownlinkFrequency1() public long getDownlinkFrequency1()
{ {
return calculateDownlink( mIdentifierUpdate1, getChannel1() ); if(mIdentifierUpdate1 != null)
{
return mIdentifierUpdate1.getDownlinkFrequency(getChannel1());
}
return 0;
} }
public long getUplinkFrequency1() public long getUplinkFrequency1()
{ {
return calculateUplink( mIdentifierUpdate1, getChannel1() ); if(mIdentifierUpdate1 != null)
{
return mIdentifierUpdate1.getUplinkFrequency(getChannel1());
}
return 0;
} }
public long getDownlinkFrequency2() public long getDownlinkFrequency2()
{ {
return calculateDownlink( mIdentifierUpdate2, getChannel2() ); if(mIdentifierUpdate2 != null)
{
return mIdentifierUpdate2.getDownlinkFrequency(getChannel2());
}
return 0;
} }
public long getUplinkFrequency2() public long getUplinkFrequency2()
{ {
return calculateUplink( mIdentifierUpdate2, getChannel2() ); if(mIdentifierUpdate2 != null)
{
return mIdentifierUpdate2.getUplinkFrequency(getChannel2());
}
return 0;
} }
@Override @Override
public void setIdentifierMessage( int identifier, IBandIdentifier message ) public void setIdentifierMessage(int identifier, IBandIdentifier message)
{ {
if( identifier == getIdentifier1() ) if(identifier == getIdentifier1())
{ {
mIdentifierUpdate1 = message; mIdentifierUpdate1 = message;
} }
if( identifier == getIdentifier2() )
{
mIdentifierUpdate2 = message;
}
}
public int[] getIdentifiers()
{
int[] idens;
if( hasChannel2() )
{
idens = new int[ 2 ];
idens[ 0 ] = getIdentifier1();
idens[ 1 ] = getIdentifier2();
}
else
{
idens = new int[ 1 ];
idens[ 0 ] = getIdentifier1();
}
return idens;
}
@Override if(identifier == getIdentifier2())
public int compareTo( SecondaryControlChannelBroadcast other ) {
mIdentifierUpdate2 = message;
}
}
public int[] getIdentifiers()
{ {
if( other.getSiteID().contentEquals( getSiteID() ) && int[] idens;
other.getIdentifier1() == getIdentifier1() &&
other.getChannel1() == getChannel1() && if(hasChannel2())
other.getChannel2() == getChannel2() && {
other.getIdentifier2() == getIdentifier2() && idens = new int[2];
other.getDownlinkFrequency1() == getDownlinkFrequency1() &&
other.getUplinkFrequency1() == getUplinkFrequency1() && idens[0] = getIdentifier1();
other.getDownlinkFrequency2() == getDownlinkFrequency2() && idens[1] = getIdentifier2();
other.getUplinkFrequency2() == getUplinkFrequency2() ) }
{ else
return 0; {
} idens = new int[1];
else if( other.getIdentifier1() < getIdentifier1() )
{ idens[0] = getIdentifier1();
return -1; }
}
else return idens;
{ }
return 1;
} @Override
public int compareTo(SecondaryControlChannelBroadcast other)
{
if(other.getRFSS().contentEquals(getRFSS()) &&
other.getSiteID().contentEquals(getSiteID()) &&
other.getIdentifier1() == getIdentifier1() &&
other.getChannel1() == getChannel1())
{
return 0;
}
else if(other.getIdentifier1() < getIdentifier1())
{
return -1;
}
else
{
return 1;
}
}
@Override
public boolean equals(Object o)
{
if(this == o)
{
return true;
}
if(!(o instanceof SecondaryControlChannelBroadcast))
{
return false;
}
SecondaryControlChannelBroadcast that = (SecondaryControlChannelBroadcast)o;
if(getRFSS() != that.getRFSS())
{
return false;
}
if(getSiteID() != that.getSiteID())
{
return false;
}
if(getIdentifier1() != that.getIdentifier1())
{
return false;
}
return getChannel1() == that.getChannel1();
}
@Override
public int hashCode()
{
int result = getRFSS() != null ? getRFSS().hashCode() : 0;
result = 31 * result + getSiteID() != null ? getSiteID().hashCode() : 0;
result = 31 * result + getIdentifier1();
result = 31 * result + getChannel1();
return result;
} }
} }

View File

@@ -1,19 +1,35 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.osp.data; package module.decode.p25.message.tsbk.osp.data;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.tsbk.GroupChannelGrant; import module.decode.p25.message.tsbk.GroupChannelGrant;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode; import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class GroupDataChannelGrant extends GroupChannelGrant public class GroupDataChannelGrant extends GroupChannelGrant
{ {
public GroupDataChannelGrant( BinaryMessage message, public GroupDataChannelGrant(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
@Override @Override

View File

@@ -1,158 +1,178 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.osp.data; package module.decode.p25.message.tsbk.osp.data;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import alias.AliasList;
import bits.BinaryMessage;
public class SNDCPDataChannelAnnouncementExplicit extends SNDCPData public class SNDCPDataChannelAnnouncementExplicit extends SNDCPData implements IdentifierReceiver
implements IdentifierReceiver
{ {
public static final int AUTONOMOUS_ACCESS_AVAILABLE_INDICATOR = 88; public static final int AUTONOMOUS_ACCESS_AVAILABLE_INDICATOR = 88;
public static final int REQUESTED_ACCESS_AVAILABLE_INDICATOR = 89; public static final int REQUESTED_ACCESS_AVAILABLE_INDICATOR = 89;
public static final int[] TRANSMIT_IDENTIFIER = {96, 97, 98, 99};
public static final int[] TRANSMIT_IDENTIFIER = { 96,97,98,99 }; public static final int[] TRANSMIT_NUMBER = {100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111};
public static final int[] TRANSMIT_NUMBER = { 100,101,102,103,104,105,106, public static final int[] RECEIVE_IDENTIFIER = {112, 113, 114, 115};
107,108,109,110,111 }; public static final int[] RECEIVE_NUMBER = {116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127};
public static final int[] RECEIVE_IDENTIFIER = { 112,113,114,115 }; public static final int[] DATA_ACCESS_CONTROL = {128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143};
public static final int[] RECEIVE_NUMBER = { 116,117,118,119,120,121,122,
123,124,125,126,127 };
public static final int[] DATA_ACCESS_CONTROL = { 128,129,130,131,132,133,
134,135,136,137,138,139,140,141,142,143 };
private IBandIdentifier mIdentifierUpdateTransmit; private IBandIdentifier mIdentifierUpdateTransmit;
private IBandIdentifier mIdentifierUpdateReceive; private IBandIdentifier mIdentifierUpdateReceive;
public SNDCPDataChannelAnnouncementExplicit( BinaryMessage message, public SNDCPDataChannelAnnouncementExplicit(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() ); sb.append(getMessageStub());
if( isEmergency() ) if(isEmergency())
{ {
sb.append( " EMERGENCY" ); sb.append(" EMERGENCY");
} }
if( isAutonomousAccessAvailable() ) if(isAutonomousAccessAvailable())
{ {
sb.append( " AUTONOMOUS ACCESS" ); sb.append(" AUTONOMOUS ACCESS");
} }
if( isRequestedAccessAvailable() ) if(isRequestedAccessAvailable())
{ {
sb.append( " DOWNLINK:" ); sb.append(" DOWNLINK:");
sb.append( getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() ); sb.append(getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber());
sb.append( " " + getUplinkFrequency() ); sb.append(" " + getUplinkFrequency());
sb.append( " UPLINK:" ); sb.append(" UPLINK:");
sb.append( getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() ); sb.append(getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber());
sb.append( " " + getDownlinkFrequency() ); sb.append(" " + getDownlinkFrequency());
sb.append( " DATA ACCESS CONTROL:" ); sb.append(" DATA ACCESS CONTROL:");
} }
else else
{ {
sb.append( " ACCESS DENIED TO DATA ACCESS CONTROL:" ); sb.append(" ACCESS DENIED TO DATA ACCESS CONTROL:");
} }
sb.append( getDataAccessControl() ); sb.append(getDataAccessControl());
return sb.toString(); return sb.toString();
} }
public boolean isAutonomousAccessAvailable() public boolean isAutonomousAccessAvailable()
{ {
return mMessage.get( AUTONOMOUS_ACCESS_AVAILABLE_INDICATOR ); return mMessage.get(AUTONOMOUS_ACCESS_AVAILABLE_INDICATOR);
} }
public boolean isRequestedAccessAvailable() public boolean isRequestedAccessAvailable()
{ {
return mMessage.get( REQUESTED_ACCESS_AVAILABLE_INDICATOR ); return mMessage.get(REQUESTED_ACCESS_AVAILABLE_INDICATOR);
} }
public int getTransmitChannelIdentifier() public int getTransmitChannelIdentifier()
{ {
return mMessage.getInt( TRANSMIT_IDENTIFIER ); return mMessage.getInt(TRANSMIT_IDENTIFIER);
} }
public int getTransmitChannelNumber() public int getTransmitChannelNumber()
{ {
return mMessage.getInt( TRANSMIT_NUMBER ); return mMessage.getInt(TRANSMIT_NUMBER);
} }
public String getTransmitChannel() public String getTransmitChannel()
{ {
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber(); return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
} }
public int getReceiveChannelIdentifier() public int getReceiveChannelIdentifier()
{ {
return mMessage.getInt( RECEIVE_IDENTIFIER ); return mMessage.getInt(RECEIVE_IDENTIFIER);
} }
public int getReceiveChannelNumber() public int getReceiveChannelNumber()
{ {
return mMessage.getInt( RECEIVE_NUMBER ); return mMessage.getInt(RECEIVE_NUMBER);
} }
public String getReceiveChannel() public String getReceiveChannel()
{ {
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber(); return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
} }
public String getDataAccessControl() public String getDataAccessControl()
{ {
return mMessage.getHex( DATA_ACCESS_CONTROL, 4 ); return mMessage.getHex(DATA_ACCESS_CONTROL, 4);
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitChannelIdentifier() )
{
mIdentifierUpdateTransmit = message;
}
else if( identifier == getReceiveChannelIdentifier() )
{
mIdentifierUpdateReceive = message;
}
else
{
throw new IllegalArgumentException( "unexpected channel band "
+ "identifier [" + identifier + "]" );
}
} }
@Override @Override
public void setIdentifierMessage(int identifier, IBandIdentifier message)
{
if(identifier == getTransmitChannelIdentifier())
{
mIdentifierUpdateTransmit = message;
}
else if(identifier == getReceiveChannelIdentifier())
{
mIdentifierUpdateReceive = message;
}
else
{
throw new IllegalArgumentException("unexpected channel band "
+ "identifier [" + identifier + "]");
}
}
@Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitChannelIdentifier();
identifiers[ 1 ] = getReceiveChannelIdentifier();
return identifiers; identifiers[0] = getTransmitChannelIdentifier();
identifiers[1] = getReceiveChannelIdentifier();
return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdateTransmit, getReceiveChannelNumber() ); if(mIdentifierUpdateTransmit != null)
{
return mIdentifierUpdateTransmit.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdateReceive, getTransmitChannelNumber() ); if(mIdentifierUpdateReceive != null)
{
mIdentifierUpdateReceive.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -1,131 +1,164 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package module.decode.p25.message.tsbk.osp.data; package module.decode.p25.message.tsbk.osp.data;
import alias.AliasList;
import bits.BinaryMessage;
import module.decode.p25.message.IBandIdentifier; import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver; import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID; import module.decode.p25.reference.DataUnitID;
import alias.AliasList;
import bits.BinaryMessage;
public class SNDCPDataChannelGrant extends SNDCPData implements IdentifierReceiver public class SNDCPDataChannelGrant extends SNDCPData implements IdentifierReceiver
{ {
public static final int[] TRANSMIT_IDENTIFIER = { 88,89,90,91 }; public static final int[] TRANSMIT_IDENTIFIER = {88, 89, 90, 91};
public static final int[] TRANSMIT_NUMBER = { 92,93,94,95,96,97,98,99,100, public static final int[] TRANSMIT_NUMBER = {92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103};
101,102,103 }; public static final int[] RECEIVE_IDENTIFIER = {104, 105, 106, 107};
public static final int[] RECEIVE_IDENTIFIER = { 104,105,106,107 }; public static final int[] RECEIVE_NUMBER = {108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
public static final int[] RECEIVE_NUMBER = { 108,109,110,111,112,113,114, public static final int[] TARGET_ADDRESS = {120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
115,116,117,118,119 }; 134, 135, 136, 137, 138, 139, 140, 141, 142, 143};
public static final int[] TARGET_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
private IBandIdentifier mIdentifierUpdateTransmit; private IBandIdentifier mIdentifierUpdateTransmit;
private IBandIdentifier mIdentifierUpdateReceive; private IBandIdentifier mIdentifierUpdateReceive;
public SNDCPDataChannelGrant( BinaryMessage message, public SNDCPDataChannelGrant(BinaryMessage message, DataUnitID duid, AliasList aliasList)
DataUnitID duid,
AliasList aliasList )
{ {
super( message, duid, aliasList ); super(message, duid, aliasList);
} }
public boolean isTDMAChannel()
{
if(mIdentifierUpdateTransmit != null)
{
return mIdentifierUpdateTransmit.isTDMA();
}
return false;
}
public String getMessage() public String getMessage()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
sb.append( " UPLINK:" );
sb.append( getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
sb.append( " " + getUplinkFrequency() );
sb.append( " DOWNLINK:" );
sb.append( getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
sb.append( " " + getDownlinkFrequency() );
sb.append( " TGT:" ); sb.append(getMessageStub());
sb.append( getTargetAddress() );
if(isEmergency())
{
sb.append(" EMERGENCY");
}
sb.append(" UPLINK:");
sb.append(getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber());
sb.append(" " + getUplinkFrequency());
sb.append(" DOWNLINK:");
sb.append(getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber());
sb.append(" " + getDownlinkFrequency());
sb.append(" TGT:");
sb.append(getTargetAddress());
return sb.toString(); return sb.toString();
} }
public int getTransmitChannelIdentifier() public int getTransmitChannelIdentifier()
{ {
return mMessage.getInt( TRANSMIT_IDENTIFIER ); return mMessage.getInt(TRANSMIT_IDENTIFIER);
} }
public int getTransmitChannelNumber() public int getTransmitChannelNumber()
{ {
return mMessage.getInt( TRANSMIT_NUMBER ); return mMessage.getInt(TRANSMIT_NUMBER);
} }
public String getTransmitChannel() public String getTransmitChannel()
{ {
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber(); return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
} }
public int getReceiveChannelIdentifier() public int getReceiveChannelIdentifier()
{ {
return mMessage.getInt( RECEIVE_IDENTIFIER ); return mMessage.getInt(RECEIVE_IDENTIFIER);
} }
public int getReceiveChannelNumber() public int getReceiveChannelNumber()
{ {
return mMessage.getInt( RECEIVE_NUMBER ); return mMessage.getInt(RECEIVE_NUMBER);
} }
public String getReceiveChannel() public String getReceiveChannel()
{ {
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber(); return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
} }
public String getTargetAddress() public String getTargetAddress()
{ {
return mMessage.getHex( TARGET_ADDRESS, 6 ); return mMessage.getHex(TARGET_ADDRESS, 6);
} }
@Override @Override
public void setIdentifierMessage( int identifier, IBandIdentifier message ) public void setIdentifierMessage(int identifier, IBandIdentifier message)
{ {
if( identifier == getTransmitChannelIdentifier() ) if(identifier == getTransmitChannelIdentifier())
{ {
mIdentifierUpdateTransmit = message; mIdentifierUpdateTransmit = message;
} }
else if( identifier == getReceiveChannelIdentifier() ) else if(identifier == getReceiveChannelIdentifier())
{ {
mIdentifierUpdateReceive = message; mIdentifierUpdateReceive = message;
} }
else else
{ {
throw new IllegalArgumentException( "unexpected channel band " throw new IllegalArgumentException("unexpected channel band "
+ "identifier [" + identifier + "]" ); + "identifier [" + identifier + "]");
} }
} }
@Override @Override
public int[] getIdentifiers() public int[] getIdentifiers()
{ {
int[] identifiers = new int[ 2 ]; int[] identifiers = new int[2];
identifiers[ 0 ] = getTransmitChannelIdentifier();
identifiers[ 1 ] = getReceiveChannelIdentifier();
return identifiers; identifiers[0] = getTransmitChannelIdentifier();
identifiers[1] = getReceiveChannelIdentifier();
return identifiers;
} }
public long getDownlinkFrequency() public long getDownlinkFrequency()
{ {
return calculateDownlink( mIdentifierUpdateTransmit, getTransmitChannelNumber() ); if(mIdentifierUpdateTransmit != null)
{
return mIdentifierUpdateTransmit.getDownlinkFrequency(getTransmitChannelNumber());
}
return 0;
} }
public long getUplinkFrequency() public long getUplinkFrequency()
{ {
return calculateUplink( mIdentifierUpdateReceive, getReceiveChannelNumber() ); if(mIdentifierUpdateReceive != null)
{
return mIdentifierUpdateReceive.getUplinkFrequency(getReceiveChannelNumber());
}
return 0;
} }
} }

View File

@@ -62,6 +62,13 @@ public class FMDemodulatorModule extends Module implements IComplexBufferListene
mIQFilter.setListener(mDemodulator); mIQFilter.setListener(mDemodulator);
} }
public FMDemodulatorModule(float[] filter)
{
mIQFilter = new ComplexFIRFilter_CB_CB(filter, 1.0f);
mDemodulator = new FMDemodulator_CB(1.0f);
mIQFilter.setListener(mDemodulator);
}
@Override @Override
public Listener<ComplexBuffer> getComplexBufferListener() public Listener<ComplexBuffer> getComplexBufferListener()
{ {

View File

@@ -163,7 +163,10 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
/** /**
* Closes the recording file. Upon successful closing of the recording file, the listener is notified that the * Closes the recording file. Upon successful closing of the recording file, the listener is notified that the
* audio recorder is closed. * audio recorder is closed. There is potential for the calling thread (here) and the buffer processor thread to
* both inform the recording closed listener that the recording is ended. So, we synchronize on the listener and
* the first thread to get the lock informs the listener and then nullifies the listener pointer so that if the
* second thread attempts a duplicate notification the listener would be null at that point.
*/ */
public void close(Listener<AudioRecorder> listener) public void close(Listener<AudioRecorder> listener)
{ {
@@ -171,8 +174,14 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
if(!mRunning.compareAndSet(true, false)) if(!mRunning.compareAndSet(true, false))
{ {
//If this recorder has already been stopped/closed, immediately inform the listener synchronized(mRecordingClosedListener)
mRecordingClosedListener.receive(this); {
if(mRecordingClosedListener != null)
{
mRecordingClosedListener.receive(AudioRecorder.this);
mRecordingClosedListener = null;
}
}
} }
} }
@@ -303,9 +312,13 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
} }
} }
if(mRecordingClosedListener != null) synchronized(mRecordingClosedListener)
{ {
mRecordingClosedListener.receive(AudioRecorder.this); if(mRecordingClosedListener != null)
{
mRecordingClosedListener.receive(AudioRecorder.this);
mRecordingClosedListener = null;
}
} }
if(mProcessorHandle != null) if(mProcessorHandle != null)

View File

@@ -18,20 +18,28 @@
******************************************************************************/ ******************************************************************************/
package sample; package sample;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.real.IOverflowListener;
import source.tuner.TunerChannelSource;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public class OverflowableTransferQueue<E> public class OverflowableTransferQueue<E>
{ {
private final static Logger mLog = LoggerFactory.getLogger(OverflowableTransferQueue.class);
public enum State {NORMAL, OVERFLOW}; public enum State {NORMAL, OVERFLOW};
private Listener<State> mStateListener; private IOverflowListener mOverflowListener;
private LinkedTransferQueue<E> mQueue = new LinkedTransferQueue<E>(); private LinkedTransferQueue<E> mQueue = new LinkedTransferQueue<E>();
private AtomicInteger mCounter = new AtomicInteger(); private AtomicInteger mCounter = new AtomicInteger();
private AtomicBoolean mOverflow = new AtomicBoolean();
private int mMaximumSize; private int mMaximumSize;
private int mResetThreshold; private int mResetThreshold;
private boolean mOverflow = false;
/** /**
* Concurrent transfer queue that couples a higher-throughput linked transfer queue with an atomic integer for * Concurrent transfer queue that couples a higher-throughput linked transfer queue with an atomic integer for
@@ -53,7 +61,7 @@ public class OverflowableTransferQueue<E>
*/ */
public void offer(E e) public void offer(E e)
{ {
if(!mOverflow) if(!mOverflow.get())
{ {
mQueue.offer(e); mQueue.offer(e);
@@ -73,46 +81,36 @@ public class OverflowableTransferQueue<E>
{ {
int drainCount = mQueue.drainTo(collection, maxElements); int drainCount = mQueue.drainTo(collection, maxElements);
if(drainCount > 0) int size = mCounter.addAndGet(-drainCount);
{
int size = mCounter.addAndGet(-drainCount);
if(mOverflow && size <= mResetThreshold) if(mOverflow.get() && size <= mResetThreshold)
{ {
setOverflow(false); setOverflow(false);
}
} }
return drainCount; return drainCount;
} }
/** /**
* Sets a listener to receive state change events * Sets a listener to receive overflow state change events
*/ */
public void setStateListener(Listener<State> listener) public void setOverflowListener(IOverflowListener listener)
{ {
mStateListener = listener; mOverflowListener = listener;
} }
/** /**
* Current state of the queue, normal or overflow * Toggles the overflow state and broadcast state change to listener
*/
public State getState()
{
return mOverflow ? State.OVERFLOW : State.NORMAL;
}
/**
* Toggles the overflow state
*/ */
private void setOverflow(boolean overflow) private void setOverflow(boolean overflow)
{ {
mOverflow = overflow; if(mOverflow.compareAndSet(!overflow, overflow))
if(mStateListener != null)
{ {
mStateListener.receive(getState()); if(mOverflowListener != null)
{
mOverflowListener.sourceOverflow(overflow);
}
} }
} }
@@ -125,7 +123,11 @@ public class OverflowableTransferQueue<E>
{ {
mQueue.clear(); mQueue.clear();
mCounter.set(0); mCounter.set(0);
mOverflow = false; mOverflow.set(false);
if(mOverflowListener != null)
{
mOverflowListener.sourceOverflow(false);
}
} }
} }
} }

View File

@@ -0,0 +1,28 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package sample.real;
public interface IOverflowListener
{
/**
* Indicates that the source is in overflow state (true) or out of overflow state (false)
* @param overflow true to indicate an overflow state
*/
void sourceOverflow(boolean overflow);
}

View File

@@ -19,6 +19,7 @@ package source;
import module.Module; import module.Module;
import sample.SampleType; import sample.SampleType;
import sample.real.IOverflowListener;
/** /**
* Abstract class to define the minimum functionality of a sample data provider. * Abstract class to define the minimum functionality of a sample data provider.
@@ -26,6 +27,7 @@ import sample.SampleType;
public abstract class Source extends Module public abstract class Source extends Module
{ {
protected SampleType mSampleType; protected SampleType mSampleType;
protected IOverflowListener mOverflowListener;
public Source( SampleType sampleType ) public Source( SampleType sampleType )
{ {
@@ -47,4 +49,25 @@ public abstract class Source extends Module
{ {
mSampleType = sampleType; mSampleType = sampleType;
} }
/**
* Registers the listener to receive overflow state changes. Use null argument to clear the listener
*/
public void setOverflowListener(IOverflowListener listener)
{
mOverflowListener = listener;
}
/**
* Broadcasts an overflow state
*
* @param overflow true if overlow, false if normal
*/
protected void broadcastOverflowState(boolean overflow)
{
if(mOverflowListener != null)
{
mOverflowListener.sourceOverflow(overflow);
}
}
} }

View File

@@ -84,7 +84,7 @@ public class LibUSBTransferProcessor
if(mRunning.compareAndSet(false, true)) if(mRunning.compareAndSet(false, true))
{ {
//Set periodicity to an odd multiple to avoid contention with transfer buffer receivers //Set periodicity to an odd multiple to avoid contention with transfer buffer receivers
mProcessorFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(mProcessor, 0L, 9L, TimeUnit.MILLISECONDS); mProcessorFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(mProcessor, 0L, 5L, TimeUnit.MILLISECONDS);
} }
} }

View File

@@ -29,6 +29,7 @@ import sample.Listener;
import sample.OverflowableTransferQueue; import sample.OverflowableTransferQueue;
import sample.complex.Complex; import sample.complex.Complex;
import sample.complex.ComplexBuffer; import sample.complex.ComplexBuffer;
import sample.real.IOverflowListener;
import source.ComplexSource; import source.ComplexSource;
import source.SourceException; import source.SourceException;
import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeEvent;
@@ -51,7 +52,7 @@ public class TunerChannelSource extends ComplexSource implements IFrequencyChang
private static final int BUFFER_MAX_CAPACITY = 300; private static final int BUFFER_MAX_CAPACITY = 300;
//Threshold for resetting buffer overflow condition //Threshold for resetting buffer overflow condition
private static final int BUFFER_OVERFLOW_RESET_THRESHOLD = 200; private static final int BUFFER_OVERFLOW_RESET_THRESHOLD = 100;
private static int CHANNEL_RATE = 48000; private static int CHANNEL_RATE = 48000;
private static int CHANNEL_PASS_FREQUENCY = 12000; private static int CHANNEL_PASS_FREQUENCY = 12000;
@@ -101,21 +102,6 @@ public class TunerChannelSource extends ComplexSource implements IFrequencyChang
mTunerFrequency = mTuner.getTunerController().getFrequency(); mTunerFrequency = mTuner.getTunerController().getFrequency();
mBuffer = new OverflowableTransferQueue<>(BUFFER_MAX_CAPACITY, BUFFER_OVERFLOW_RESET_THRESHOLD); mBuffer = new OverflowableTransferQueue<>(BUFFER_MAX_CAPACITY, BUFFER_OVERFLOW_RESET_THRESHOLD);
mBuffer.setStateListener(new Listener<OverflowableTransferQueue.State>()
{
@Override
public void receive(OverflowableTransferQueue.State state)
{
if(state == OverflowableTransferQueue.State.NORMAL)
{
mLog.debug("Channel [" + mTunerFrequency + "] buffer overflow - temporary pause until processing catches up");
}
else
{
mLog.debug("Channel [" + mTunerFrequency + "] buffer overflow cleared - resuming normal processing");
}
}
});
/* Setup the frequency translator to the current source frequency */ /* Setup the frequency translator to the current source frequency */
long frequencyOffset = mTunerFrequency - mTunerChannel.getFrequency(); long frequencyOffset = mTunerFrequency - mTunerChannel.getFrequency();
@@ -126,6 +112,14 @@ public class TunerChannelSource extends ComplexSource implements IFrequencyChang
frequencyChanged(new FrequencyChangeEvent(Event.NOTIFICATION_SAMPLE_RATE_CHANGE, mTuner.getTunerController().getSampleRate())); frequencyChanged(new FrequencyChangeEvent(Event.NOTIFICATION_SAMPLE_RATE_CHANGE, mTuner.getTunerController().getSampleRate()));
} }
/**
* Overrides the default source overflow listener management to delegate responsibility to the overflow buffer
*/
@Override
public void setOverflowListener(IOverflowListener listener)
{
mBuffer.setOverflowListener(listener);
}
public void start(ScheduledExecutorService executor) public void start(ScheduledExecutorService executor)
{ {
@@ -175,7 +169,7 @@ public class TunerChannelSource extends ComplexSource implements IFrequencyChang
} }
else else
{ {
mLog.warn("Attempt to stop() and already stopped tuner channel source was ignored"); mLog.warn("Attempt to stop() an already stopped tuner channel source was ignored");
} }
} }
@@ -379,6 +373,10 @@ public class TunerChannelSource extends ComplexSource implements IFrequencyChang
mLog.error("Error encountered during decimation process", e); mLog.error("Error encountered during decimation process", e);
} }
} }
catch(Throwable throwable)
{
mLog.error("Code error encountered during decimation process - channel thread will probably die", throwable);
}
/* Check to see if we've been shutdown */ /* Check to see if we've been shutdown */
if(!mProcessing) if(!mProcessing)

View File

@@ -30,6 +30,7 @@ import sample.Listener;
import sample.OverflowableTransferQueue; import sample.OverflowableTransferQueue;
import sample.adapter.ISampleAdapter; import sample.adapter.ISampleAdapter;
import sample.complex.ComplexBuffer; import sample.complex.ComplexBuffer;
import sample.real.IOverflowListener;
import source.tuner.TunerManager; import source.tuner.TunerManager;
import util.ThreadPool; import util.ThreadPool;
@@ -56,7 +57,7 @@ public class USBTransferProcessor implements TransferCallback
private static final int FILLED_BUFFER_MAX_CAPACITY = 300; private static final int FILLED_BUFFER_MAX_CAPACITY = 300;
//Threshold for resetting buffer overflow condition //Threshold for resetting buffer overflow condition
private static final int FILLED_BUFFER_OVERFLOW_RESET_THRESHOLD = 200; private static final int FILLED_BUFFER_OVERFLOW_RESET_THRESHOLD = 100;
private String mDeviceName; private String mDeviceName;
@@ -101,12 +102,12 @@ public class USBTransferProcessor implements TransferCallback
mBufferSize = bufferSize; mBufferSize = bufferSize;
mFilledBuffers = new OverflowableTransferQueue<>(FILLED_BUFFER_MAX_CAPACITY, FILLED_BUFFER_OVERFLOW_RESET_THRESHOLD); mFilledBuffers = new OverflowableTransferQueue<>(FILLED_BUFFER_MAX_CAPACITY, FILLED_BUFFER_OVERFLOW_RESET_THRESHOLD);
mFilledBuffers.setStateListener(new Listener<OverflowableTransferQueue.State>() mFilledBuffers.setOverflowListener(new IOverflowListener()
{ {
@Override @Override
public void receive(OverflowableTransferQueue.State state) public void sourceOverflow(boolean overflow)
{ {
if(state == OverflowableTransferQueue.State.NORMAL) if(overflow)
{ {
mLog.debug(mDeviceName + " - buffer overflow - temporary pause until processing catches up"); mLog.debug(mDeviceName + " - buffer overflow - temporary pause until processing catches up");
} }
@@ -300,6 +301,7 @@ public class USBTransferProcessor implements TransferCallback
{ {
case LibUsb.TRANSFER_COMPLETED: case LibUsb.TRANSFER_COMPLETED:
case LibUsb.TRANSFER_STALL: case LibUsb.TRANSFER_STALL:
case LibUsb.TRANSFER_TIMED_OUT:
if(transfer.actualLength() > 0) if(transfer.actualLength() > 0)
{ {
ByteBuffer buffer = transfer.buffer(); ByteBuffer buffer = transfer.buffer();