mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-11 16:17:24 -05:00
Compare commits
36 Commits
v0.4.0-bet
...
v0.4.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1bc56c500 | ||
|
|
d1d115d11f | ||
|
|
aca41b4f6e | ||
|
|
1e3ae996ac | ||
|
|
b3b2e74688 | ||
|
|
44237bec5c | ||
|
|
53b44f44e3 | ||
|
|
9af7a184ad | ||
|
|
9c8d87ec64 | ||
|
|
4c34968d28 | ||
|
|
2d71f5173a | ||
|
|
2e942113c6 | ||
|
|
e20540ccc6 | ||
|
|
8d7e0e9f46 | ||
|
|
cc5d94f58d | ||
|
|
26197e433c | ||
|
|
f54b4dfd0e | ||
|
|
085ba52294 | ||
|
|
b8c24680a5 | ||
|
|
c658582157 | ||
|
|
83e518d503 | ||
|
|
2163d0f822 | ||
|
|
34c920eede | ||
|
|
35b0b5ef9b | ||
|
|
08672c33bd | ||
|
|
e2651d6c7c | ||
|
|
851a4e12d2 | ||
|
|
b7c66ec844 | ||
|
|
7522a3a820 | ||
|
|
6a0402d1cf | ||
|
|
5309af84f7 | ||
|
|
8d8d77fa11 | ||
|
|
284cf07e97 | ||
|
|
16414c7585 | ||
|
|
70c9eed0bf | ||
|
|
f49b1fef17 |
68
README.md
68
README.md
@@ -2,9 +2,10 @@
|
||||
A cross-platform java application for decoding, monitoring, recording and streaming trunked mobile and related radio protocols using Software Defined Radios (SDR).
|
||||
|
||||
* [Getting Started](https://github.com/DSheirer/sdrtrunk/wiki/GettingStarted_V0.3.0)
|
||||
* [User's Manual Version 0.3.0](https://github.com/DSheirer/sdrtrunk/wiki/UserManual_V0.3.0)
|
||||
* [User's Manual Version 0.3.0 and 0.4.0](https://github.com/DSheirer/sdrtrunk/wiki/UserManual_V0.3.0)
|
||||
* [Download](https://github.com/DSheirer/sdrtrunk/releases)
|
||||
* [Support](https://groups.google.com/forum/#!forum/sdrtrunk)
|
||||
* [Support Group](https://groups.google.com/forum/#!forum/sdrtrunk)
|
||||
* [Discord Support Channel](https://discord.gg/HJQaKYE)
|
||||
|
||||

|
||||
**Figure 1:** sdrtrunk **Version 0.3.0** Application Screenshot
|
||||
@@ -13,68 +14,53 @@ A cross-platform java application for decoding, monitoring, recording and stream
|
||||
|
||||
If you simply want to download and run the program, please follow these instructions.
|
||||
|
||||
## Install Java 8 (or newer)
|
||||
|
||||
## Download the latest sdrtrunk release
|
||||
## Download the latest sdrtrunk release for your operating system
|
||||
|
||||
All release versions of sdrtrunk are available from the [releases](https://github.com/DSheirer/sdrtrunk/releases) tab.
|
||||
|
||||
**(final)** These versions have been tested and are the current release version.
|
||||
* **(alpha)** These versions are under development feature previews and likely to contain bugs and unexpected behavior.
|
||||
* **(beta)** These versions are currently being tested for bugs and functionality prior to final release.
|
||||
* **(final)** These versions have been tested and are the current release version.
|
||||
|
||||
**(alpha)** These versions are under development feature previews and likely to contain bugs and unexpected behavior.
|
||||
## Unzip the release
|
||||
|
||||
**(beta)** These versions are currently being tested for bugs and functionality.
|
||||
Use 7-zip or any zip utility to unzip the release file
|
||||
|
||||
## Run the application
|
||||
## Start the application
|
||||
|
||||
Either double-click on the downloaded file (if supported on your operating system) or open a terminal/command window
|
||||
and change to the directory where you downloaded the release file and type:
|
||||
|
||||
```
|
||||
java -jar downloaded-jar-filename
|
||||
```
|
||||
|
||||
Note: replace _downloaded-jar-filename_ with the actual name of the sdrtrunk release version that you downloaded
|
||||
Once unzipped, open a command prompt to where you unzipped the release. Change to the **/bin** directory and use the launch script to start the application:
|
||||
* **Windows** sdr-trunk.bat
|
||||
* **Linux/OSX** ./sdr-trunk
|
||||
|
||||
## Optional - P25 Audio
|
||||
If you're using sdrtrunk with a P25 trunked radio system, the [JMBE](https://github.com/DSheirer/sdrtrunk/wiki/JMBE) wiki page contains instructions
|
||||
for downloading the JMBE audio library source code and compiling the JMBE library. Copy the resulting JMBE audio library
|
||||
jar file to the same folder containing the sdrtrunk application to use the library with sdrtrunk.
|
||||
If you're using sdrtrunk with a P25 trunked radio system, the [JMBE](https://github.com/DSheirer/sdrtrunk/wiki/JMBE) wiki page contains instructions for downloading the JMBE audio library source code and compiling the JMBE library. Once you have compiled the library, launch the sdrtrunk application. From the menu bar, choose **View >> Preferences**. In the **JMBE Audio Codec** section, update the path to where your compiled JMBE library is located. Any channels that are started after you set the path will be able to produce P25 audio.
|
||||
|
||||
## Minimum System Requirements
|
||||
* **Operating System:** Windows (32 or 64-bit), Linux (32 or 64-bit) or Mac/Linux (64-bit, 10.14 or higher)
|
||||
* **CPU:** 4-core
|
||||
* **RAM:** 8GB or more (preferred). Depending on usage, 4GB may be sufficient.
|
||||
|
||||
# Developer Instructions:
|
||||
|
||||
If you're interested in modifying and/or compiling the source code, please follow these instructions to use gradle to compile the code.
|
||||
|
||||
## Build the project
|
||||
sdrtrunk uses gradle as the build system. You can build it with locally installed gradle or if you do not have/want
|
||||
to install gradle you can use preconfigured linux/windows wrapper.
|
||||
sdrtrunk uses the gradle build system. This requires OpenJDK 11 or higher installed on your local compuber. Use the gradle wrapper to build the source code:
|
||||
|
||||
### Build with locally installed gradle 4.3.1
|
||||
### Linux
|
||||
```
|
||||
gradle clean buildSdr
|
||||
./gradlew clean build
|
||||
```
|
||||
### Build with preconfigured wrapper for linux/windows
|
||||
Linux
|
||||
### Windows
|
||||
```
|
||||
./gradlew clean buildSdr
|
||||
gradlew.bat clean build
|
||||
```
|
||||
Windows
|
||||
```
|
||||
gradlew.bat clean buildSdr
|
||||
```
|
||||
This would add gradle, download all project dependencies and build JAR
|
||||
|
||||
The **/build/distributions** folder will contain the zip file of the compiled program. Unzip it and launch the program from the scripts in the **/bin** directory.
|
||||
|
||||
## Development
|
||||
All dependencies/versions are controlled from build.gradle.
|
||||
To change the new release version tag of artifact - change property:
|
||||
```
|
||||
version = '0.3.2'
|
||||
```
|
||||
|
||||
## Run SDRTrunk
|
||||
SDRTrunk is packed into single uber-jar file. There is need to have folders with dependencies and
|
||||
adding them with classpath. Just run with java.
|
||||
### Use Java8
|
||||
```
|
||||
java -jar build/libs/sdr-trunk-all-0.3.2.jar
|
||||
version = '0.4.0'
|
||||
```
|
||||
|
||||
226
build.gradle
226
build.gradle
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -30,9 +30,10 @@ plugins {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://jitpack.io" }
|
||||
}
|
||||
|
||||
version = '0.4.0-beta.1'
|
||||
version = '0.4.0-beta.5'
|
||||
sourceCompatibility = '11'
|
||||
|
||||
sourceSets {
|
||||
@@ -41,28 +42,42 @@ sourceSets {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.assertj:assertj-core:3.8.0'
|
||||
compile fileTree(dir: 'imports', include: '*.jar')
|
||||
compile 'ch.qos.logback:logback-core:1.2.3'
|
||||
compile 'ch.qos.logback:logback-classic:1.2.3'
|
||||
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.8'
|
||||
compile 'com.fazecast:jSerialComm:2.5.0'
|
||||
compile 'com.github.jiconfont:jiconfont-font_awesome:4.7.0.1'
|
||||
compile 'com.github.jiconfont:jiconfont-javafx:1.0.0'
|
||||
compile 'com.github.jiconfont:jiconfont-swing:1.0.1'
|
||||
compile 'com.github.wendykierp:JTransforms:3.1'
|
||||
compile 'com.google.guava:guava:27.0.1-jre'
|
||||
compile 'com.jidesoft:jide-oss:3.6.18'
|
||||
compile 'com.miglayout:miglayout-swing:5.2'
|
||||
compile 'eu.hansolo:charts:1.0.5'
|
||||
compile 'io.github.dsheirer:radio-reference-api:15.0.1'
|
||||
compile 'javax.usb:usb-api:1.0.2'
|
||||
compile 'net.coderazzi:tablefilter-swing:5.4.0'
|
||||
compile 'org.apache.commons:commons-lang3:3.8.1'
|
||||
compile 'org.apache.commons:commons-io:1.3.2'
|
||||
compile 'org.apache.mina:mina-core:2.0.19'
|
||||
compile 'org.apache.mina:mina-http:2.0.19'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation 'org.assertj:assertj-core:3.8.0'
|
||||
|
||||
//Jitpack imports
|
||||
implementation 'com.github.nwaldispuehl:java-lame:v3.98.4'
|
||||
implementation 'com.github.dnault:libresample4j:master'
|
||||
implementation 'com.github.DSheirer.jmbe:jmbe-api:1.0.0'
|
||||
|
||||
//mavenCentral/jcenter imports
|
||||
implementation 'org.apache.commons:commons-math3:3.6.1'
|
||||
implementation 'ch.qos.logback:logback-core:1.2.3'
|
||||
implementation 'ch.qos.logback:logback-classic:1.2.3'
|
||||
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.8'
|
||||
implementation 'com.fazecast:jSerialComm:2.5.0'
|
||||
implementation 'com.github.jiconfont:jiconfont-font_awesome:4.7.0.1'
|
||||
implementation 'com.github.jiconfont:jiconfont-javafx:1.0.0'
|
||||
implementation 'com.github.jiconfont:jiconfont-swing:1.0.1'
|
||||
implementation 'com.github.wendykierp:JTransforms:3.1'
|
||||
implementation 'com.google.guava:guava:27.0.1-jre'
|
||||
implementation 'com.jidesoft:jide-oss:3.6.18'
|
||||
implementation 'com.miglayout:miglayout-swing:5.2'
|
||||
implementation 'eu.hansolo:charts:1.0.5'
|
||||
implementation 'io.github.dsheirer:radio-reference-api:15.1.2'
|
||||
implementation 'javax.usb:usb-api:1.0.2'
|
||||
implementation 'net.coderazzi:tablefilter-swing:5.4.0'
|
||||
implementation 'org.apache.commons:commons-lang3:3.8.1'
|
||||
implementation 'org.apache.commons:commons-io:1.3.2'
|
||||
implementation 'org.apache.mina:mina-core:2.0.19'
|
||||
implementation 'org.apache.mina:mina-http:2.0.19'
|
||||
implementation 'org.slf4j:slf4j-api:1.7.25'
|
||||
implementation 'org.usb4java:libusb4java:1.3.0'
|
||||
implementation 'org.usb4java:usb4java:1.3.0'
|
||||
implementation 'org.usb4java:usb4java-javax:1.3.0'
|
||||
implementation 'pl.edu.icm:JLargeArrays:1.6'
|
||||
|
||||
//The must remain as compile options to ensure they are included in the build to produce multi-OS images
|
||||
compile "org.openjfx:javafx-base:11:win"
|
||||
compile "org.openjfx:javafx-base:11:linux"
|
||||
compile "org.openjfx:javafx-base:11:mac"
|
||||
@@ -75,11 +90,6 @@ dependencies {
|
||||
compile "org.openjfx:javafx-swing:11.0.2:win"
|
||||
compile "org.openjfx:javafx-swing:11.0.2:linux"
|
||||
compile "org.openjfx:javafx-swing:11.0.2:mac"
|
||||
compile 'org.slf4j:slf4j-api:1.7.25'
|
||||
compile 'org.usb4java:libusb4java:1.3.0'
|
||||
compile 'org.usb4java:usb4java:1.3.0'
|
||||
compile 'org.usb4java:usb4java-javax:1.3.0'
|
||||
compile 'pl.edu.icm:JLargeArrays:1.6'
|
||||
}
|
||||
|
||||
application {
|
||||
@@ -100,128 +110,110 @@ javafx {
|
||||
jar {
|
||||
manifest {
|
||||
attributes (
|
||||
'Implementation-Title' : 'sdrtrunk project',
|
||||
'Implementation-Version' : archiveVersion,
|
||||
'Class-Path' : 'jmbe-1.0.0.jar',
|
||||
'Created-By' : "Gradle ${gradle.gradleVersion}",
|
||||
'Build-Timestamp' : new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(new Date()),
|
||||
'Build-JDK' : "${System.properties['java.version']} (${System.properties['java.vendor']} ${System.properties['java.vm.version']}",
|
||||
'Build-OS' : "${System.properties['os.name']} (${System.properties['os.arch']} ${System.properties['os.version']}"
|
||||
'Implementation-Title' : 'sdrtrunk project',
|
||||
'Implementation-Version' : archiveVersion,
|
||||
'Class-Path' : 'jmbe-1.0.1.jar',
|
||||
'Created-By' : "Gradle ${gradle.gradleVersion}",
|
||||
'Build-Timestamp' : new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(new Date()),
|
||||
'Build-JDK' : "${System.properties['java.version']} (${System.properties['java.vendor']} ${System.properties['java.vm.version']}",
|
||||
'Build-OS' : "${System.properties['os.name']} (${System.properties['os.arch']} ${System.properties['os.version']}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Java Development Kit (JDK) locations. These paths must point to the 'bin' directory
|
||||
* within a JDK for each of the specified architectures. These JDKs are used by the
|
||||
* runtime and runtimeZip tasks to produce platform-specific builds
|
||||
* Java Development Kit (JDK) locations. In order to build OS-specific images, these paths must point to the 'bin'
|
||||
* directory within a JDK for each of the specified architectures. These JDKs are used by the runtime and runtimeZip
|
||||
* tasks to produce platform-specific builds. If none of these paths exists, then an image will be created for the
|
||||
* host OS using the installed JDK.
|
||||
*/
|
||||
def jdkLinux_x64 = '/media/denny/WD250GB/java/bellsoft/linux-x64/jdk-13.0.1'
|
||||
def jdkLinux_x86 = '/media/denny/WD250GB/java/bellsoft/linux-x86/jdk-13.0.1'
|
||||
def jdkOsx_x64 = '/media/denny/WD250GB/java/bellsoft/osx-x64/jdk-13.0.1.jdk'
|
||||
def jdkWindows_x64 = '/media/denny/WD250GB/java/bellsoft/windows-x64/jdk-13.0.1'
|
||||
def jdkWindows_x86 = '/media/denny/WD250GB/java/bellsoft/windows-x86/jdk-13.0.1'
|
||||
//def jdkLinux_aarch64 = '/media/denny/WD250GB/java/bellsoft/linux-aarch64/jdk-11.0.2'
|
||||
//def jdkLinux_arm32 = '/media/denny/WD250GB/java/bellsoft/linux-arm32/jdk-11.0.2'
|
||||
//def jfxLinux_arm32 = '/media/denny/WD250GB/java/bellsoft/linux-arm32/armv6hf-sdk/lib'
|
||||
def jdk_linux_x86_64 = '/media/denny/WD250GB/java/bellsoft/linux-x64/jdk-13.0.1'
|
||||
def jdk_linux_x86_32 = '/media/denny/WD250GB/java/bellsoft/linux-x86/jdk-13.0.1'
|
||||
def jdk_osx_x86_64 = '/media/denny/WD250GB/java/bellsoft/osx-x64/jdk-13.0.1.jdk'
|
||||
def jdk_windows_x86_64 = '/media/denny/WD250GB/java/bellsoft/windows-x64/jdk-13.0.1'
|
||||
def jdk_windows_x86_32 = '/media/denny/WD250GB/java/bellsoft/windows-x86/jdk-13.0.1'
|
||||
|
||||
def file_jdk_linux_x86_64 = new File(jdk_linux_x86_64)
|
||||
def file_jdk_linux_x86_32 = new File(jdk_linux_x86_32)
|
||||
def file_jdk_osx_x86_64 = new File(jdk_osx_x86_64)
|
||||
def file_jdk_windows_x86_64 = new File(jdk_windows_x86_64)
|
||||
def file_jdk_windows_x86_32 = new File(jdk_windows_x86_32)
|
||||
|
||||
def hasTargetJdk = file_jdk_linux_x86_32.exists() ||
|
||||
file_jdk_linux_x86_64.exists() ||
|
||||
file_jdk_osx_x86_64.exists() ||
|
||||
file_jdk_windows_x86_32.exists() ||
|
||||
file_jdk_windows_x86_64.exists()
|
||||
|
||||
runtime {
|
||||
targetPlatform('linux-x64', jdkLinux_x64)
|
||||
targetPlatform('linux-x86', jdkLinux_x86)
|
||||
targetPlatform('osx-x64', jdkOsx_x64)
|
||||
targetPlatform('windows-x64', jdkWindows_x64)
|
||||
targetPlatform('windows-x86', jdkWindows_x86)
|
||||
// targetPlatform('linux-aarch64', jdkLinux_aarch64)
|
||||
// targetPlatform('linux-arm32', jdkLinux_arm32)
|
||||
if(file_jdk_linux_x86_64.exists())
|
||||
{
|
||||
targetPlatform('linux-x86_64-v' + version, jdk_linux_x86_64)
|
||||
}
|
||||
|
||||
if(file_jdk_linux_x86_32.exists())
|
||||
{
|
||||
targetPlatform('linux-x86_32-v' + version, jdk_linux_x86_32)
|
||||
}
|
||||
|
||||
if(file_jdk_osx_x86_64.exists())
|
||||
{
|
||||
targetPlatform('osx-x86_64-v' + version, jdk_osx_x86_64)
|
||||
}
|
||||
|
||||
if(file_jdk_windows_x86_64.exists())
|
||||
{
|
||||
targetPlatform('windows-x86_64-v' + version, jdk_windows_x86_64)
|
||||
}
|
||||
|
||||
if(file_jdk_windows_x86_32.exists())
|
||||
{
|
||||
targetPlatform('windows-x86_32-v' + version, jdk_windows_x86_32)
|
||||
}
|
||||
|
||||
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
|
||||
modules = ['java.desktop', 'java.naming', 'jdk.unsupported', 'jdk.unsupported.desktop']
|
||||
imageZip = file("$buildDir/image/sdr-trunk-" + version + ".zip")
|
||||
modules = ['java.desktop', 'java.naming', 'jdk.unsupported', 'jdk.unsupported.desktop', 'java.net.http']
|
||||
imageZip = hasTargetJdk ? file("$buildDir/image/sdr-trunk.zip") : file("$buildDir/image/sdr-trunk-" + version + ".zip")
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for existence of JDK folders for each supported platform before creating runtime images
|
||||
*/
|
||||
tasks.runtime.doFirst {
|
||||
def linux_x64 = new File(jdkLinux_x64)
|
||||
|
||||
if(!linux_x64.exists())
|
||||
if(!file_jdk_linux_x86_64.exists())
|
||||
{
|
||||
println("Linux x64 JDK was not found at " + jdkLinux_x64)
|
||||
throw new GradleException("Cannot find Java Development Kit (JDK) for linux-x64 architecture. " +
|
||||
"Please update the build.gradle script to provide the correct path")
|
||||
println("Skipping OS Image - Linux x86 64-bit JDK was not found at " + jdk_linux_x86_64)
|
||||
}
|
||||
|
||||
def linux_x86 = new File(jdkLinux_x86)
|
||||
|
||||
if(!linux_x86.exists())
|
||||
if(!file_jdk_linux_x86_32.exists())
|
||||
{
|
||||
println("Linux x86 JDK was not found at " + jdkLinux_x86)
|
||||
throw new GradleException("Cannot find Java Development Kit (JDK) for linux-x86 32-bit architecture. " +
|
||||
"Please update the build.gradle script to provide the correct path")
|
||||
println("Skipping OS Image - Linux x86 32-bit JDK was not found at " + jdk_linux_x86_32)
|
||||
}
|
||||
|
||||
def osx_x64 = new File(jdkOsx_x64)
|
||||
|
||||
if(!osx_x64.exists())
|
||||
if(!file_jdk_osx_x86_64.exists())
|
||||
{
|
||||
println("OSX x64 JDK was not found at " + jdkOsx_x64);
|
||||
throw new GradleException("Cannot find Java Development Kit (JDK) for osx-x64 architecture. " +
|
||||
"Please update the build.gradle script to provide the correct path")
|
||||
println("Skipping OS Image - OSX x86 64-bit JDK was not found at " + jdk_osx_x86_64);
|
||||
}
|
||||
|
||||
def windows_x64 = new File(jdkWindows_x64)
|
||||
|
||||
if(!windows_x64.exists())
|
||||
if(!file_jdk_windows_x86_64.exists())
|
||||
{
|
||||
println("Windows x64 JDK was not found at " + jdkWindows_x64)
|
||||
throw new GradleException("Cannot find Java Development Kit (JDK) for windows-x64 architecture. " +
|
||||
"Please update the build.gradle script to provide the correct path")
|
||||
println("Skipping OS Image - Windows x86 64-bit JDK was not found at " + jdk_windows_x86_64)
|
||||
}
|
||||
|
||||
def windows_x86 = new File(jdkWindows_x86)
|
||||
|
||||
if(!windows_x86.exists())
|
||||
if(!file_jdk_windows_x86_32.exists())
|
||||
{
|
||||
println("Windows x86 32-bit JDK was not found at " + jdkWindows_x86)
|
||||
throw new GradleException("Cannot find Java Development Kit (JDK) for windows-x64 architecture. " +
|
||||
"Please update the build.gradle script to provide the correct path")
|
||||
println("Skipping OS Image - Windows x86 32-bit JDK was not found at " + jdk_windows_x86_32)
|
||||
}
|
||||
|
||||
// def linux_aarch64 = new File(jdkLinux_aarch64)
|
||||
//
|
||||
// if(!linux_aarch64.exists())
|
||||
// {
|
||||
// println("Linux aarch64 JDK was not found at " + jdkLinux_aarch64)
|
||||
// throw new GradleException("Cannot find Java Development Kit (JDK) for linux-aarch64 architecture. " +
|
||||
// "Please update the build.gradle script to provide the correct path")
|
||||
// }
|
||||
//
|
||||
// def linux_arm32 = new File(jdkLinux_arm32)
|
||||
//
|
||||
// if(!linux_arm32.exists())
|
||||
// {
|
||||
// println("Linux arm32 JDK was not found at " + jdkLinux_arm32)
|
||||
// throw new GradleException("Cannot find Java Development Kit (JDK) for linux-arm32 architecture. " +
|
||||
// "Please update the build.gradle script to provide the correct path")
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Since we have to list each of the platform-specific JavaFX libraries as dependencies,
|
||||
* remove them from each build image
|
||||
* Remove unused JavaFX OS-specific libraries from each platform target directory
|
||||
*/
|
||||
tasks.runtime.doLast {
|
||||
delete(fileTree('build/image/sdr-trunk-linux-x64/lib').include { it.name ==~ /javafx.*-(win|mac)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-linux-x86/lib').include { it.name ==~ /javafx.*-(win|mac)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-osx-x64/lib').include { it.name ==~ /javafx.*-(win|linux)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-windows-x64/lib').include { it.name ==~ /javafx.*-(linux|mac)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-windows-x86/lib').include { it.name ==~ /javafx.*-(linux|mac)\.jar/ })
|
||||
|
||||
// delete(fileTree('build/image/sdr-trunk-linux-aarch64/lib').include { it.name ==~ /javafx.*-(win|mac)\.jar/ })
|
||||
// delete(fileTree('build/image/sdr-trunk-linux-arm32/lib').include { it.name ==~ /javafx.*-(win|mac)\.jar/ })
|
||||
// copy {
|
||||
// from(jfxLinux_arm32).exclude("src.zip")
|
||||
// into 'build/image/sdr-trunk-linux-arm32/lib'
|
||||
// }
|
||||
delete(fileTree('build/image/sdr-trunk-linux-x86_64-v' + version + '/lib').include { it.name ==~ /javafx.*-(win|mac)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-linux-x86_32-v' + version + '/lib').include { it.name ==~ /javafx.*-(win|mac)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-osx-x86_64-v' + version + '/lib').include { it.name ==~ /javafx.*-(win|linux)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-windows-x86_64-v' + version + '/lib').include { it.name ==~ /javafx.*-(linux|mac)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-windows-x86_32-v' + version + '/lib').include { it.name ==~ /javafx.*-(linux|mac)\.jar/ })
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias;
|
||||
|
||||
@@ -37,30 +39,34 @@ import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncID;
|
||||
import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncIDEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.mdc.MDC1200ID;
|
||||
import io.github.dsheirer.alias.id.legacy.mdc.MDC1200IDEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.mobileID.MINEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.mobileID.Min;
|
||||
import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327ID;
|
||||
import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327IDEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordable;
|
||||
import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordableEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
|
||||
import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupIDEditor;
|
||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||
import io.github.dsheirer.alias.id.lojack.LoJackIDEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.mobileID.MINEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.mobileID.Min;
|
||||
import io.github.dsheirer.alias.id.priority.Priority;
|
||||
import io.github.dsheirer.alias.id.priority.PriorityEditor;
|
||||
import io.github.dsheirer.alias.id.record.Record;
|
||||
import io.github.dsheirer.alias.id.record.RecordEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.siteID.SiteID;
|
||||
import io.github.dsheirer.alias.id.legacy.siteID.SiteIDEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
|
||||
import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupIDEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueIDEditor;
|
||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||
import io.github.dsheirer.alias.id.lojack.LoJackIDEditor;
|
||||
import io.github.dsheirer.alias.id.priority.Priority;
|
||||
import io.github.dsheirer.alias.id.priority.PriorityEditor;
|
||||
import io.github.dsheirer.alias.id.radio.Radio;
|
||||
import io.github.dsheirer.alias.id.radio.RadioEditor;
|
||||
import io.github.dsheirer.alias.id.radio.RadioRange;
|
||||
import io.github.dsheirer.alias.id.radio.RadioRangeEditor;
|
||||
import io.github.dsheirer.alias.id.record.Record;
|
||||
import io.github.dsheirer.alias.id.record.RecordEditor;
|
||||
import io.github.dsheirer.alias.id.status.StatusID;
|
||||
import io.github.dsheirer.alias.id.status.StatusIDEditor;
|
||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupEditor;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRangeEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueIDEditor;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||
import io.github.dsheirer.gui.editor.Editor;
|
||||
import io.github.dsheirer.gui.editor.EmptyEditor;
|
||||
@@ -102,6 +108,15 @@ public class AliasFactory
|
||||
Priority copyPriority = new Priority();
|
||||
copyPriority.setPriority(originalPriority.getPriority());
|
||||
return copyPriority;
|
||||
case RADIO_ID:
|
||||
Radio originalRadio = (Radio)id;
|
||||
Radio copyRadio = new Radio(originalRadio.getProtocol(), originalRadio.getValue());
|
||||
return copyRadio;
|
||||
case RADIO_ID_RANGE:
|
||||
RadioRange originalRadioRange = (RadioRange)id;
|
||||
RadioRange copyRadioRange = new RadioRange(originalRadioRange.getProtocol(), originalRadioRange.getMinRadio(),
|
||||
originalRadioRange.getMaxRadio());
|
||||
return copyRadioRange;
|
||||
case RECORD:
|
||||
return new Record();
|
||||
case SITE:
|
||||
@@ -213,6 +228,10 @@ public class AliasFactory
|
||||
return new MINEditor(aliasID);
|
||||
case PRIORITY:
|
||||
return new PriorityEditor(aliasID);
|
||||
case RADIO_ID:
|
||||
return new RadioEditor(aliasID);
|
||||
case RADIO_ID_RANGE:
|
||||
return new RadioRangeEditor(aliasID);
|
||||
case RECORD:
|
||||
return new RecordEditor(aliasID);
|
||||
case SITE:
|
||||
@@ -286,6 +305,10 @@ public class AliasFactory
|
||||
return new NonRecordable();
|
||||
case PRIORITY:
|
||||
return new Priority();
|
||||
case RADIO_ID:
|
||||
return new Radio();
|
||||
case RADIO_ID_RANGE:
|
||||
return new RadioRange();
|
||||
case RECORD:
|
||||
return new Record();
|
||||
case TALKGROUP:
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias;
|
||||
|
||||
@@ -24,6 +26,8 @@ import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||
import io.github.dsheirer.alias.id.esn.Esn;
|
||||
import io.github.dsheirer.alias.id.priority.Priority;
|
||||
import io.github.dsheirer.alias.id.radio.Radio;
|
||||
import io.github.dsheirer.alias.id.radio.RadioRange;
|
||||
import io.github.dsheirer.alias.id.status.StatusID;
|
||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
||||
@@ -32,6 +36,7 @@ import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
import io.github.dsheirer.identifier.esn.ESNIdentifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroupIdentifier;
|
||||
import io.github.dsheirer.identifier.radio.RadioIdentifier;
|
||||
import io.github.dsheirer.identifier.status.UnitStatusIdentifier;
|
||||
import io.github.dsheirer.identifier.status.UserStatusIdentifier;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
@@ -48,10 +53,15 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* List of aliases that share the same alias list name and provides convenient methods for looking up alias
|
||||
* objects that match an identifier.
|
||||
*/
|
||||
public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(AliasList.class);
|
||||
private Map<Protocol,TalkgroupAliasList> mTalkgroupProtocolMap = new HashMap<>();
|
||||
private Map<Protocol,RadioAliasList> mRadioProtocolMap = new HashMap<>();
|
||||
private Map<String,Alias> mESNMap = new HashMap<>();
|
||||
private Map<Integer,Alias> mStatusMap = new HashMap<>();
|
||||
private boolean mHasAliasActions = false;
|
||||
@@ -124,6 +134,32 @@ public class AliasList implements Listener<AliasEvent>
|
||||
|
||||
talkgroupRangeAliasList.add(talkgroupRange, alias);
|
||||
break;
|
||||
case RADIO_ID:
|
||||
Radio radio = (Radio)id;
|
||||
|
||||
RadioAliasList radioAliasList = mRadioProtocolMap.get(radio.getProtocol());
|
||||
|
||||
if(radioAliasList == null)
|
||||
{
|
||||
radioAliasList = new RadioAliasList();
|
||||
mRadioProtocolMap.put(radio.getProtocol(), radioAliasList);
|
||||
}
|
||||
|
||||
radioAliasList.add(radio, alias);
|
||||
break;
|
||||
case RADIO_ID_RANGE:
|
||||
RadioRange radioRange = (RadioRange)id;
|
||||
|
||||
RadioAliasList radioRangeAliasList = mRadioProtocolMap.get(radioRange.getProtocol());
|
||||
|
||||
if(radioRangeAliasList == null)
|
||||
{
|
||||
radioRangeAliasList = new RadioAliasList();
|
||||
mRadioProtocolMap.put(radioRange.getProtocol(), radioRangeAliasList);
|
||||
}
|
||||
|
||||
radioRangeAliasList.add(radioRange, alias);
|
||||
break;
|
||||
case ESN:
|
||||
String esn = ((Esn) id).getEsn();
|
||||
|
||||
@@ -253,14 +289,7 @@ public class AliasList implements Listener<AliasEvent>
|
||||
|
||||
if(talkgroupAliasList != null)
|
||||
{
|
||||
Alias alias = talkgroupAliasList.getAlias(talkgroup);
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
aliases.add(alias);
|
||||
return aliases;
|
||||
}
|
||||
return toList(talkgroupAliasList.getAlias(talkgroup));
|
||||
}
|
||||
break;
|
||||
case PATCH_GROUP:
|
||||
@@ -293,53 +322,52 @@ public class AliasList implements Listener<AliasEvent>
|
||||
return aliases;
|
||||
}
|
||||
break;
|
||||
case RADIO:
|
||||
RadioIdentifier radio = (RadioIdentifier)identifier;
|
||||
|
||||
RadioAliasList radioAliasList = mRadioProtocolMap.get(identifier.getProtocol());
|
||||
|
||||
if(radioAliasList != null)
|
||||
{
|
||||
return toList(radioAliasList.getAlias(radio));
|
||||
}
|
||||
break;
|
||||
case ESN:
|
||||
if(identifier instanceof ESNIdentifier)
|
||||
{
|
||||
Alias alias = getESNAlias(((ESNIdentifier)identifier).getValue());
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
aliases.add(alias);
|
||||
return aliases;
|
||||
}
|
||||
return toList(getESNAlias(((ESNIdentifier)identifier).getValue()));
|
||||
}
|
||||
break;
|
||||
case UNIT_STATUS:
|
||||
if(identifier instanceof UnitStatusIdentifier)
|
||||
{
|
||||
int status = ((UnitStatusIdentifier)identifier).getValue();
|
||||
|
||||
Alias alias = mStatusMap.get(status);
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
aliases.add(alias);
|
||||
return aliases;
|
||||
}
|
||||
return toList(mStatusMap.get(status));
|
||||
}
|
||||
break;
|
||||
case USER_STATUS:
|
||||
if(identifier instanceof UserStatusIdentifier)
|
||||
{
|
||||
int status = ((UserStatusIdentifier)identifier).getValue();
|
||||
|
||||
Alias alias = mStatusMap.get(status);
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
aliases.add(alias);
|
||||
return aliases;
|
||||
}
|
||||
return toList(mStatusMap.get(status));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.EMPTY_LIST;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static List<Alias> toList(Alias alias)
|
||||
{
|
||||
if(alias != null)
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
aliases.add(alias);
|
||||
return aliases;
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -553,4 +581,87 @@ public class AliasList implements Listener<AliasEvent>
|
||||
AliasList.remove(alias, mTalkgroupRangeAliasMap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listing of radio IDs and ranges for a specific protocol
|
||||
*/
|
||||
public class RadioAliasList
|
||||
{
|
||||
private Map<Integer,Alias> mRadioAliasMap = new TreeMap<>();
|
||||
private Map<RadioRange, Alias> mRadioRangeAliasMap = new HashMap<>();
|
||||
|
||||
public RadioAliasList()
|
||||
{
|
||||
}
|
||||
|
||||
public Alias getAlias(RadioIdentifier identifier)
|
||||
{
|
||||
int value = identifier.getValue();
|
||||
|
||||
if(mRadioAliasMap.containsKey(value))
|
||||
{
|
||||
return mRadioAliasMap.get(value);
|
||||
}
|
||||
|
||||
for(RadioRange radioRange: mRadioRangeAliasMap.keySet())
|
||||
{
|
||||
if(radioRange.contains(value))
|
||||
{
|
||||
return mRadioRangeAliasMap.get(radioRange);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void add(Radio radio, Alias alias)
|
||||
{
|
||||
//Detect collisions
|
||||
if(mRadioAliasMap.containsKey(radio.getValue()))
|
||||
{
|
||||
Alias existing = mRadioAliasMap.get(radio.getValue());
|
||||
|
||||
mLog.warn("Alias [" + alias.getName() + "] radio ID [" + radio.getValue() +
|
||||
"] has the same value as alias [" + existing.getName() +
|
||||
"] - alias [" + alias.getName() + "] will be used for alias list [" + getName() + "]");
|
||||
}
|
||||
|
||||
mRadioAliasMap.put(radio.getValue(), alias);
|
||||
}
|
||||
|
||||
public void add(RadioRange radioRange, Alias alias)
|
||||
{
|
||||
//Log warning if the new range overlaps with any existing ranges
|
||||
for(Map.Entry<RadioRange,Alias> entry: mRadioRangeAliasMap.entrySet())
|
||||
{
|
||||
if(radioRange.overlaps(entry.getKey()))
|
||||
{
|
||||
mLog.warn("Alias [" + alias.getName() + "] with radio ID range [" + radioRange.toString() +
|
||||
"] overlaps with alias [" + entry.getValue().getName() +
|
||||
"] with range [" + entry.getKey().toString() + "] for alias list [" + getName() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
mRadioRangeAliasMap.put(radioRange, alias);
|
||||
}
|
||||
|
||||
public void remove(Radio radio)
|
||||
{
|
||||
mRadioAliasMap.remove(radio.getValue());
|
||||
}
|
||||
|
||||
public void remove(RadioRange radioRange)
|
||||
{
|
||||
mRadioRangeAliasMap.remove(radioRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the alias from all internal maps
|
||||
*/
|
||||
public void remove(Alias alias)
|
||||
{
|
||||
AliasList.remove(alias, mRadioAliasMap);
|
||||
AliasList.remove(alias, mRadioRangeAliasMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.alias.id;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
@@ -25,18 +29,20 @@ import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||
import io.github.dsheirer.alias.id.esn.Esn;
|
||||
import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncID;
|
||||
import io.github.dsheirer.alias.id.legacy.mdc.MDC1200ID;
|
||||
import io.github.dsheirer.alias.id.legacy.mobileID.Min;
|
||||
import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327ID;
|
||||
import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordable;
|
||||
import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
|
||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||
import io.github.dsheirer.alias.id.legacy.mobileID.Min;
|
||||
import io.github.dsheirer.alias.id.priority.Priority;
|
||||
import io.github.dsheirer.alias.id.record.Record;
|
||||
import io.github.dsheirer.alias.id.legacy.siteID.SiteID;
|
||||
import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
|
||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||
import io.github.dsheirer.alias.id.priority.Priority;
|
||||
import io.github.dsheirer.alias.id.radio.Radio;
|
||||
import io.github.dsheirer.alias.id.radio.RadioRange;
|
||||
import io.github.dsheirer.alias.id.record.Record;
|
||||
import io.github.dsheirer.alias.id.status.StatusID;
|
||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
|
||||
@JsonSubTypes({
|
||||
@@ -48,6 +54,8 @@ import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
||||
@JsonSubTypes.Type(value = Min.class, name = "min"),
|
||||
@JsonSubTypes.Type(value = MPT1327ID.class, name = "mpt1327ID"),
|
||||
@JsonSubTypes.Type(value = NonRecordable.class, name = "nonRecordable"),
|
||||
@JsonSubTypes.Type(value = Radio.class, name = "radio"),
|
||||
@JsonSubTypes.Type(value = RadioRange.class, name = "radioRange"),
|
||||
@JsonSubTypes.Type(value = Talkgroup.class, name = "talkgroup"),
|
||||
@JsonSubTypes.Type(value = TalkgroupRange.class, name = "talkgroupRange"),
|
||||
@JsonSubTypes.Type(value = Priority.class, name = "priority"),
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id;
|
||||
|
||||
@@ -28,6 +30,8 @@ public enum AliasIDType
|
||||
LTR_NET_UID("LTR-Net UID"),
|
||||
MIN("Passport MIN"),
|
||||
PRIORITY("Audio Priority"),
|
||||
RADIO_ID("Radio ID"),
|
||||
RADIO_ID_RANGE("Radio ID Range"),
|
||||
RECORD("Record"),
|
||||
SITE("Site"),
|
||||
STATUS("Status"),
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id;
|
||||
|
||||
@@ -124,6 +126,8 @@ public class AliasIdentifierEditor extends Editor<Alias>
|
||||
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.TALKGROUP));
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.TALKGROUP_RANGE));
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.RADIO_ID));
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.RADIO_ID_RANGE));
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.ESN));
|
||||
// menu.add(new AddAliasIdentifierItem(AliasIDType.LOJACK));
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.STATUS));
|
||||
|
||||
118
src/main/java/io/github/dsheirer/alias/id/radio/Radio.java
Normal file
118
src/main/java/io/github/dsheirer/alias/id/radio/Radio.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.radio;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupFormat;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupFormatter;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
* Integer radio identifier with protocol.
|
||||
*/
|
||||
public class Radio extends AliasID
|
||||
{
|
||||
private Protocol mProtocol = Protocol.UNKNOWN;
|
||||
private int mValue;
|
||||
|
||||
public Radio()
|
||||
{
|
||||
//No arg JAXB constructor
|
||||
}
|
||||
|
||||
public Radio(Protocol protocol, int value)
|
||||
{
|
||||
mProtocol = protocol;
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "value")
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public void setValue(int value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "protocol")
|
||||
public Protocol getProtocol()
|
||||
{
|
||||
return mProtocol;
|
||||
}
|
||||
|
||||
public void setProtocol(Protocol protocol)
|
||||
{
|
||||
mProtocol = protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
if(mProtocol == null || mProtocol == Protocol.UNKNOWN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TalkgroupFormat talkgroupFormat = TalkgroupFormat.get(mProtocol);
|
||||
return talkgroupFormat.getMinimumValidValue() <= mValue && mValue <= talkgroupFormat.getMaximumValidValue();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("Radio ID:").append(TalkgroupFormatter.format(mProtocol, mValue));
|
||||
sb.append(" Protocol:").append((mProtocol));
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append(" **NOT VALID**");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(AliasID id)
|
||||
{
|
||||
if(id instanceof Radio)
|
||||
{
|
||||
Radio tgid = (Radio)id;
|
||||
return (getProtocol() == tgid.getProtocol()) && (getValue() == tgid.getValue());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
|
||||
@Override
|
||||
public AliasIDType getType()
|
||||
{
|
||||
return AliasIDType.RADIO_ID;
|
||||
}
|
||||
}
|
||||
235
src/main/java/io/github/dsheirer/alias/id/radio/RadioEditor.java
Normal file
235
src/main/java/io/github/dsheirer/alias/id/radio/RadioEditor.java
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.radio;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.text.MaskFormatter;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.ParseException;
|
||||
|
||||
public class RadioEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(RadioEditor.class);
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String VALID_CHARACTERS_FOR_ASTERISK_MASKS = "0123456789 ";
|
||||
private MaskFormatter mMaskFormatter = new MaskFormatter();
|
||||
private JComboBox<Protocol> mComboProtocol;
|
||||
private JFormattedTextField mRadioIdField;
|
||||
|
||||
|
||||
public RadioEditor(AliasID aliasID)
|
||||
{
|
||||
initGUI();
|
||||
setItem(aliasID);
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
|
||||
|
||||
add(new JLabel("Protocol:"));
|
||||
|
||||
mComboProtocol = new JComboBox<>();
|
||||
|
||||
DefaultComboBoxModel<Protocol> model = new DefaultComboBoxModel<>();
|
||||
|
||||
for(Protocol protocol : Protocol.RADIO_ID_PROTOCOLS)
|
||||
{
|
||||
model.addElement(protocol);
|
||||
}
|
||||
|
||||
mComboProtocol.setModel(model);
|
||||
mComboProtocol.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
Protocol protocol = (Protocol)mComboProtocol.getSelectedItem();
|
||||
updateEditor(protocol);
|
||||
setModified(true);
|
||||
}
|
||||
});
|
||||
|
||||
add(mComboProtocol);
|
||||
|
||||
add(new JLabel("Value:"));
|
||||
|
||||
mRadioIdField = new JFormattedTextField(mMaskFormatter);
|
||||
mRadioIdField.getDocument().addDocumentListener(this);
|
||||
add(mRadioIdField, "growx,push");
|
||||
|
||||
JLabel help = new JLabel("Help ...");
|
||||
help.setForeground(Color.BLUE.brighter());
|
||||
help.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
help.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
RadioFormat radioFormat = RadioFormat.get(getCurrentProtocol());
|
||||
JOptionPane.showMessageDialog(RadioEditor.this,
|
||||
radioFormat.getValidRangeHelpText(), "Help", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
});
|
||||
add(help, "align left");
|
||||
}
|
||||
|
||||
private void updateEditor(Protocol protocol)
|
||||
{
|
||||
RadioFormat mask = RadioFormat.get(protocol);
|
||||
int currentValue = 0;
|
||||
Radio radio = getRadio();
|
||||
|
||||
if(radio != null)
|
||||
{
|
||||
currentValue = radio.getValue();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mRadioIdField.setValue(null);
|
||||
mRadioIdField.setToolTipText(mask.getValidRangeHelpText());
|
||||
mMaskFormatter.setMask(mask.getMask());
|
||||
if(mask.getMask().contains("*"))
|
||||
{
|
||||
mMaskFormatter.setValidCharacters(VALID_CHARACTERS_FOR_ASTERISK_MASKS);
|
||||
}
|
||||
mRadioIdField.setValue(RadioFormatter.format(protocol, currentValue));
|
||||
}
|
||||
catch(ParseException pe)
|
||||
{
|
||||
mLog.error("Error applying talkgroup editor mask to mask formatter [" + mask.getMask() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private Protocol getCurrentProtocol()
|
||||
{
|
||||
return mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Current talkgroup alias id
|
||||
*/
|
||||
public Radio getRadio()
|
||||
{
|
||||
if(getItem() instanceof Radio)
|
||||
{
|
||||
return (Radio)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(AliasID aliasID)
|
||||
{
|
||||
super.setItem(aliasID);
|
||||
|
||||
Radio radio = getRadio();
|
||||
|
||||
if(radio != null)
|
||||
{
|
||||
Protocol currentProtocol = getCurrentProtocol();
|
||||
if(currentProtocol == radio.getProtocol())
|
||||
{
|
||||
updateEditor(radio.getProtocol());
|
||||
}
|
||||
mComboProtocol.getModel().setSelectedItem(radio.getProtocol());
|
||||
|
||||
String formatted = RadioFormatter.format(radio.getProtocol(), radio.getValue());
|
||||
mRadioIdField.setValue(formatted);
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboProtocol.getModel().setSelectedItem(Protocol.UNKNOWN);
|
||||
mRadioIdField.setValue(RadioFormatter.format(getCurrentProtocol(), 0));
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
Radio radio = getRadio();
|
||||
|
||||
if(radio != null)
|
||||
{
|
||||
Protocol protocol = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
|
||||
|
||||
if(protocol == null)
|
||||
{
|
||||
protocol = Protocol.UNKNOWN;
|
||||
}
|
||||
|
||||
int value = -1;
|
||||
|
||||
try
|
||||
{
|
||||
value = RadioFormatter.parse(protocol, mRadioIdField.getText());
|
||||
}
|
||||
catch(ParseException pe)
|
||||
{
|
||||
//ignore ... value is still -1 and outside valid value range
|
||||
}
|
||||
|
||||
RadioFormat mask = RadioFormat.get(protocol);
|
||||
|
||||
//Check for valid value within range ... notify user but allow value to persist
|
||||
if(value < mask.getMinimumValidValue() || value > mask.getMaximumValidValue())
|
||||
{
|
||||
String message = "Invalid value [" + mRadioIdField.getText() + "]. " + protocol.name() +
|
||||
" valid range is [" + mask.getValidRangeDescription() + "]";
|
||||
|
||||
JOptionPane.showMessageDialog(RadioEditor.this, message, "Invalid Radio ID Value",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
radio.setValue(value);
|
||||
}
|
||||
|
||||
radio.setProtocol(protocol);
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
}
|
||||
}
|
||||
117
src/main/java/io/github/dsheirer/alias/id/radio/RadioFormat.java
Normal file
117
src/main/java/io/github/dsheirer/alias/id/radio/RadioFormat.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.id.radio;
|
||||
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
* Radio ID protocol identifier entry masks and min/max valid ranges and valid range descriptions
|
||||
*
|
||||
* Note: the getMask() value is intended for use with a MaskFormatter attached to a JFormattedTextField. The
|
||||
* protocol masks that have a dash (-) use the # (any digit) character and the protocol masks that do not have
|
||||
* a formatting dash use an asterisk (*). Within the editor(s) that use this enumeration, the editor must use
|
||||
* a setValidCharacters() on the mask formatter whenever it detects the mask containing one or more asterisks.
|
||||
*/
|
||||
public enum RadioFormat
|
||||
{
|
||||
APCO25("********", 0, 0xFFFFFF, "0 to 16,777,215",
|
||||
"<html>APCO25 valid range is 0 to 16,777,215"),
|
||||
UNKNOWN("********", 1, 0xFFFFFF, "1 to 16,777,215",
|
||||
"Unknown protocol valid value range is 1-16,777,215");
|
||||
|
||||
private String mMask;
|
||||
private int mMinimumValue;
|
||||
private int mMaximumValue;
|
||||
private String mValidRangeDescription;
|
||||
private String mValidRangeHelpText;
|
||||
|
||||
RadioFormat(String mask, int minimumValue, int maximumValue, String validRangeDescription, String validRangeHelpText)
|
||||
{
|
||||
mMask = mask;
|
||||
mMinimumValue = minimumValue;
|
||||
mMaximumValue = maximumValue;
|
||||
mValidRangeDescription = validRangeDescription;
|
||||
mValidRangeHelpText = validRangeHelpText;
|
||||
}
|
||||
|
||||
public String getMask()
|
||||
{
|
||||
return mMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimum valid value for the protocol
|
||||
*/
|
||||
public int getMinimumValidValue()
|
||||
{
|
||||
return mMinimumValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum valid value for the protocol
|
||||
*/
|
||||
public int getMaximumValidValue()
|
||||
{
|
||||
return mMaximumValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the value is valid for the protocol
|
||||
*/
|
||||
public boolean isValid(int value)
|
||||
{
|
||||
return getMinimumValidValue() <= value && value <= getMaximumValidValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Short description of the valid value range
|
||||
*/
|
||||
public String getValidRangeDescription()
|
||||
{
|
||||
return mValidRangeDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Help text for valid value ranges
|
||||
*/
|
||||
public String getValidRangeHelpText()
|
||||
{
|
||||
return mValidRangeHelpText;
|
||||
}
|
||||
|
||||
public static RadioFormat get(Protocol protocol)
|
||||
{
|
||||
if(protocol == null)
|
||||
{
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
switch(protocol)
|
||||
{
|
||||
case APCO25:
|
||||
return APCO25;
|
||||
default:
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.id.radio;
|
||||
|
||||
import io.github.dsheirer.preference.identifier.talkgroup.APCO25TalkgroupFormatter;
|
||||
import io.github.dsheirer.preference.identifier.talkgroup.IntegerFormatter;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Protocol-specific formatting of radio id values and parsing of formatted radio id values.
|
||||
*/
|
||||
public class RadioFormatter
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(RadioFormatter.class);
|
||||
private static Map<Protocol,IntegerFormatter> mFormatterMap = new HashMap<>();
|
||||
|
||||
static
|
||||
{
|
||||
mFormatterMap.put(Protocol.APCO25, new APCO25TalkgroupFormatter());
|
||||
mFormatterMap.put(Protocol.UNKNOWN, new IntegerFormatter());
|
||||
}
|
||||
|
||||
public RadioFormatter()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the formatted value into an integer using a protocol specific formatter
|
||||
*/
|
||||
public static int parse(Protocol protocol, String value) throws ParseException
|
||||
{
|
||||
IntegerFormatter formatter = mFormatterMap.get(protocol);
|
||||
|
||||
if(formatter == null)
|
||||
{
|
||||
formatter = mFormatterMap.get(Protocol.UNKNOWN);
|
||||
}
|
||||
|
||||
return formatter.parse(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the integer value using a protocol-specific formatter
|
||||
*/
|
||||
public static String format(Protocol protocol, int value)
|
||||
{
|
||||
IntegerFormatter formatter = mFormatterMap.get(protocol);
|
||||
|
||||
if(formatter == null)
|
||||
{
|
||||
formatter = mFormatterMap.get(Protocol.UNKNOWN);
|
||||
}
|
||||
|
||||
return formatter.format(value);
|
||||
}
|
||||
}
|
||||
166
src/main/java/io/github/dsheirer/alias/id/radio/RadioRange.java
Normal file
166
src/main/java/io/github/dsheirer/alias/id/radio/RadioRange.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.radio;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
* Integer radio identifier range of values with protocol.
|
||||
*/
|
||||
public class RadioRange extends AliasID
|
||||
{
|
||||
private Protocol mProtocol = Protocol.UNKNOWN;
|
||||
private int mMinRadio;
|
||||
private int mMaxRadio;
|
||||
|
||||
public RadioRange()
|
||||
{
|
||||
//No arg JAXB constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a radio range of from - to radio values (inclusive) for the specified protocol
|
||||
* @param protocol for the radio range
|
||||
* @param minRadio starting or minimum radio value
|
||||
* @param maxRadio ending or maximum radio value
|
||||
*/
|
||||
public RadioRange(Protocol protocol, int minRadio, int maxRadio)
|
||||
{
|
||||
mProtocol = protocol;
|
||||
mMinRadio = minRadio;
|
||||
mMaxRadio = maxRadio;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "min")
|
||||
public int getMinRadio()
|
||||
{
|
||||
return mMinRadio;
|
||||
}
|
||||
|
||||
public void setMinRadio(int minRadio)
|
||||
{
|
||||
mMinRadio = minRadio;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "max")
|
||||
public int getMaxRadio()
|
||||
{
|
||||
return mMaxRadio;
|
||||
}
|
||||
|
||||
public void setMaxRadio(int maxRadio)
|
||||
{
|
||||
mMaxRadio = maxRadio;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "protocol")
|
||||
public Protocol getProtocol()
|
||||
{
|
||||
return mProtocol;
|
||||
}
|
||||
|
||||
public void setProtocol(Protocol protocol)
|
||||
{
|
||||
mProtocol = protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
if(mProtocol == null || mProtocol == Protocol.UNKNOWN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RadioFormat radioFormat = RadioFormat.get(mProtocol);
|
||||
return radioFormat.getMinimumValidValue() <= mMinRadio &&
|
||||
mMinRadio <= radioFormat.getMaximumValidValue() &&
|
||||
radioFormat.getMinimumValidValue() <= mMaxRadio &&
|
||||
mMaxRadio <= radioFormat.getMaximumValidValue();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("Radio ID Range:").append(RadioFormatter.format(mProtocol, mMinRadio));
|
||||
sb.append(" to ").append(RadioFormatter.format(mProtocol, mMaxRadio));
|
||||
sb.append(" Protocol:").append(mProtocol != null ? mProtocol : "unspecified");
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append(" **NOT VALID**");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(AliasID id)
|
||||
{
|
||||
if(id instanceof RadioRange)
|
||||
{
|
||||
RadioRange tgid = (RadioRange)id;
|
||||
return (getProtocol() == tgid.getProtocol()) &&
|
||||
(getMinRadio() == tgid.getMinRadio()) &&
|
||||
(getMaxRadio() == tgid.getMaxRadio());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this radio range contains/includes the value
|
||||
* @param radioValue
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(int radioValue)
|
||||
{
|
||||
return getMinRadio() <= radioValue && radioValue <= getMaxRadio();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this talkgroup range overlaps the talkgroup range argument.
|
||||
* @param radioRange to check for overlap
|
||||
* @return true if the ranges overlap
|
||||
*/
|
||||
public boolean overlaps(RadioRange radioRange)
|
||||
{
|
||||
return contains(radioRange.getMinRadio()) ||
|
||||
contains(radioRange.getMaxRadio()) ||
|
||||
(getMinRadio() < radioRange.getMinRadio() &&
|
||||
radioRange.getMaxRadio() < getMaxRadio()) ||
|
||||
(radioRange.getMinRadio() < getMinRadio() &&
|
||||
getMaxRadio() < radioRange.getMaxRadio());
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
|
||||
@Override
|
||||
public AliasIDType getType()
|
||||
{
|
||||
return AliasIDType.RADIO_ID_RANGE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.radio;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.text.MaskFormatter;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.ParseException;
|
||||
|
||||
public class RadioRangeEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(RadioRangeEditor.class);
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String VALID_CHARACTERS_FOR_ASTERISK_MASKS = "0123456789 ";
|
||||
private MaskFormatter mMaskFormatter = new MaskFormatter();
|
||||
private JComboBox<Protocol> mComboProtocol;
|
||||
private JFormattedTextField mMinRadioField;
|
||||
private JFormattedTextField mMaxRadioField;
|
||||
|
||||
public RadioRangeEditor(AliasID aliasID)
|
||||
{
|
||||
initGUI();
|
||||
|
||||
setItem(aliasID);
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
|
||||
|
||||
add(new JLabel("Protocol:"));
|
||||
|
||||
mComboProtocol = new JComboBox<Protocol>();
|
||||
|
||||
DefaultComboBoxModel<Protocol> model = new DefaultComboBoxModel<>();
|
||||
|
||||
for(Protocol protocol : Protocol.RADIO_ID_PROTOCOLS)
|
||||
{
|
||||
model.addElement(protocol);
|
||||
}
|
||||
|
||||
mComboProtocol.setModel(model);
|
||||
mComboProtocol.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
Protocol protocol = (Protocol)mComboProtocol.getSelectedItem();
|
||||
updateEditor(protocol);
|
||||
setModified(true);
|
||||
}
|
||||
});
|
||||
|
||||
add(mComboProtocol);
|
||||
|
||||
add(new JLabel("Min:"));
|
||||
|
||||
mMinRadioField = new JFormattedTextField(mMaskFormatter);
|
||||
mMinRadioField.getDocument().addDocumentListener(this);
|
||||
add(mMinRadioField, "growx,push");
|
||||
|
||||
add(new JLabel("Max:"));
|
||||
|
||||
mMaxRadioField = new JFormattedTextField(mMaskFormatter);
|
||||
mMaxRadioField.getDocument().addDocumentListener(this);
|
||||
add(mMaxRadioField, "growx,push");
|
||||
|
||||
JLabel help = new JLabel("Help ...");
|
||||
help.setForeground(Color.BLUE.brighter());
|
||||
help.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
help.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
RadioFormat radioFormat = RadioFormat.get(getCurrentProtocol());
|
||||
JOptionPane.showMessageDialog(RadioRangeEditor.this,
|
||||
radioFormat.getValidRangeHelpText(), "Help", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
});
|
||||
add(help, "align left");
|
||||
}
|
||||
|
||||
private void updateEditor(Protocol protocol)
|
||||
{
|
||||
RadioFormat mask = RadioFormat.get(protocol);
|
||||
int currentMinValue = 0;
|
||||
int currentMaxValue = 0;
|
||||
RadioRange radioRange = getRadioRange();
|
||||
|
||||
if(radioRange != null)
|
||||
{
|
||||
currentMinValue = radioRange.getMinRadio();
|
||||
currentMaxValue = radioRange.getMaxRadio();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mMinRadioField.setValue(null);
|
||||
mMaxRadioField.setValue(null);
|
||||
|
||||
mMinRadioField.setToolTipText(mask.getValidRangeHelpText());
|
||||
mMaxRadioField.setToolTipText(mask.getValidRangeHelpText());
|
||||
mMaskFormatter.setMask(mask.getMask());
|
||||
if(mask.getMask().contains("*"))
|
||||
{
|
||||
mMaskFormatter.setValidCharacters(VALID_CHARACTERS_FOR_ASTERISK_MASKS);
|
||||
}
|
||||
|
||||
mMinRadioField.setValue(RadioFormatter.format(protocol, currentMinValue));
|
||||
mMaxRadioField.setValue(RadioFormatter.format(protocol, currentMaxValue));
|
||||
}
|
||||
catch(ParseException pe)
|
||||
{
|
||||
mLog.error("Error applying radio editor mask to mask formatter [" + mask.getMask() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private Protocol getCurrentProtocol()
|
||||
{
|
||||
return mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public RadioRange getRadioRange()
|
||||
{
|
||||
if(getItem() instanceof RadioRange)
|
||||
{
|
||||
return (RadioRange)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(AliasID aliasID)
|
||||
{
|
||||
super.setItem(aliasID);
|
||||
|
||||
RadioRange radioRange = getRadioRange();
|
||||
|
||||
updateEditor(radioRange.getProtocol());
|
||||
|
||||
if(radioRange != null)
|
||||
{
|
||||
mComboProtocol.getModel().setSelectedItem(radioRange.getProtocol());
|
||||
String minFormatted = RadioFormatter.format(radioRange.getProtocol(), radioRange.getMinRadio());
|
||||
mMinRadioField.setValue(minFormatted);
|
||||
String maxFormatted = RadioFormatter.format(radioRange.getProtocol(), radioRange.getMaxRadio());
|
||||
mMaxRadioField.setValue(maxFormatted);
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboProtocol.getModel().setSelectedItem(Protocol.UNKNOWN);
|
||||
mMinRadioField.setValue(RadioFormatter.format(getCurrentProtocol(), 0));
|
||||
mMaxRadioField.setValue(RadioFormatter.format(getCurrentProtocol(), 0));
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
RadioRange radioRange = getRadioRange();
|
||||
|
||||
if(radioRange != null)
|
||||
{
|
||||
Protocol protocol = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
|
||||
|
||||
if(protocol == null)
|
||||
{
|
||||
protocol = Protocol.UNKNOWN;
|
||||
}
|
||||
|
||||
radioRange.setProtocol(protocol);
|
||||
|
||||
int minValue = -1;
|
||||
int maxValue = -1;
|
||||
|
||||
try
|
||||
{
|
||||
minValue = RadioFormatter.parse(protocol, mMinRadioField.getText());
|
||||
}
|
||||
catch(ParseException pe)
|
||||
{
|
||||
//ignore ... value is still -1 and outside valid value range
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
maxValue = RadioFormatter.parse(protocol, mMaxRadioField.getText());
|
||||
}
|
||||
catch(ParseException pe)
|
||||
{
|
||||
//ignore ... value is still -1 and outside valid value range
|
||||
}
|
||||
|
||||
RadioFormat mask = RadioFormat.get(protocol);
|
||||
|
||||
//Check for valid value within range ... notify user but allow value to persist
|
||||
if(minValue < mask.getMinimumValidValue() || minValue > mask.getMaximumValidValue())
|
||||
{
|
||||
String message = "Invalid minimum value [" + mMinRadioField.getText() + "]. " + protocol.name() +
|
||||
" valid range is [" + mask.getValidRangeDescription() + "]";
|
||||
|
||||
JOptionPane.showMessageDialog(RadioRangeEditor.this, message,
|
||||
"Invalid Radio Value", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
radioRange.setMinRadio(minValue);
|
||||
}
|
||||
|
||||
//Check for valid value within range ... notify user but allow value to persist
|
||||
if(maxValue < mask.getMinimumValidValue() || maxValue > mask.getMaximumValidValue())
|
||||
{
|
||||
String message = "Invalid maximum value [" + mMaxRadioField.getText() + "]. " + protocol.name() +
|
||||
" valid range is [" + mask.getValidRangeDescription() + "]";
|
||||
|
||||
JOptionPane.showMessageDialog(RadioRangeEditor.this, message,
|
||||
"Invalid Radio Value", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
radioRange.setMaxRadio(maxValue);
|
||||
}
|
||||
|
||||
radioRange.setProtocol(protocol);
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.id.talkgroup;
|
||||
@@ -32,8 +34,8 @@ import io.github.dsheirer.protocol.Protocol;
|
||||
*/
|
||||
public enum TalkgroupFormat
|
||||
{
|
||||
APCO25("********", 1, 0xFFFFFF, "1 to 16,777,215",
|
||||
"<html>APCO25 valid range is 1 to 65,535(talkgroup)<br>or 1 to 16,777,215 (radio ID)"),
|
||||
APCO25("********", 0, 0xFFFFFF, "0 to 65,535",
|
||||
"<html>APCO25 talkgroup valid range is 0 to 65,535"),
|
||||
FLEETSYNC("###-####", 1, 0x7FFFFF, "001-0001 to 127-8192",
|
||||
"<html>Fleetsync valid ranges are 1-127(prefix)<br>and 1-8192(ident) (ie. 001-0001 to 127-8192)"),
|
||||
LTR("##-###", 257, 5375, "01-001 to 20-255",
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import io.github.dsheirer.audio.convert.ISilenceGenerator;
|
||||
@@ -201,6 +204,10 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
mAudioRecordingQueue.offer(recording);
|
||||
broadcast(new BroadcastEvent(this, BroadcastEvent.Event.BROADCASTER_QUEUE_CHANGE));
|
||||
}
|
||||
else
|
||||
{
|
||||
recording.removePendingReplay();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -373,9 +380,9 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
broadcastAudio(mSilenceGenerator.generate(PROCESSOR_RUN_INTERVAL_MS));
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
catch(Throwable t)
|
||||
{
|
||||
mLog.error("Error while processing audio streaming queue", e);
|
||||
mLog.error("Error while processing audio streaming queue", t);
|
||||
}
|
||||
|
||||
mProcessing.set(false);
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast;
|
||||
|
||||
@@ -200,7 +202,16 @@ public class StreamManager implements Listener<ReusableAudioPacket>
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(BroadcastModel.TEMPORARY_STREAM_FILE_SUFFIX);
|
||||
sb.append(sNextRecordingNumber.incrementAndGet()).append("_");
|
||||
|
||||
int recordingNumber = sNextRecordingNumber.incrementAndGet();
|
||||
|
||||
//Check for integer overflow and readjust negative value to 0
|
||||
if(recordingNumber < 0)
|
||||
{
|
||||
sNextRecordingNumber.set(0);
|
||||
recordingNumber = sNextRecordingNumber.incrementAndGet();
|
||||
}
|
||||
sb.append(recordingNumber).append("_");
|
||||
sb.append(TimeStamp.getLongTimeStamp("_"));
|
||||
sb.append(mBroadcastFormat.getFileExtension());
|
||||
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast.icecast;
|
||||
|
||||
@@ -31,43 +33,26 @@ import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.properties.SystemProperties;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.apache.mina.core.RuntimeIoException;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.mina.http.HttpClientCodec;
|
||||
import org.apache.mina.http.HttpRequestImpl;
|
||||
import org.apache.mina.http.api.HttpMethod;
|
||||
import org.apache.mina.http.api.HttpRequest;
|
||||
import org.apache.mina.http.api.HttpVersion;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.channels.UnresolvedAddressException;
|
||||
import java.util.HashMap;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdater
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(IcecastBroadcastMetadataUpdater.class);
|
||||
private final static String UTF8 = "UTF-8";
|
||||
|
||||
private HttpClient mHttpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
|
||||
private IcecastConfiguration mIcecastConfiguration;
|
||||
private AliasModel mAliasModel;
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private AtomicBoolean mUpdating = new AtomicBoolean();
|
||||
private Queue<String> mMetadataQueue = new LinkedTransferQueue<>();
|
||||
private Map<String,String> mHTTPHeaders;
|
||||
private boolean mStackTraceLoggingSuppressed;
|
||||
private boolean mConnectionLoggingSuppressed = false;
|
||||
|
||||
/**
|
||||
* Icecast song metadata updater. Each metadata update is processed in the order received and the dispatch of
|
||||
@@ -81,41 +66,6 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
mAliasModel = aliasModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Socket connector - lazy constructor.
|
||||
*/
|
||||
private NioSocketConnector getSocketConnector()
|
||||
{
|
||||
if(mSocketConnector == null)
|
||||
{
|
||||
mSocketConnector = new NioSocketConnector();
|
||||
// mSocketConnector.getFilterChain().addLast("logger", new LoggingFilter(IcecastBroadcastMetadataUpdater.class));
|
||||
mSocketConnector.getFilterChain().addLast("http_client_codec", new HttpClientCodec());
|
||||
|
||||
//Each metadata update session is single-use, so we'll shut it down upon success or failure
|
||||
mSocketConnector.setHandler(new IoHandlerAdapter()
|
||||
{
|
||||
@Override
|
||||
public void exceptionCaught(IoSession session, Throwable cause) throws Exception
|
||||
{
|
||||
//Single-use session - close it after we receive an error
|
||||
session.closeNow();
|
||||
|
||||
mLog.error("Metadata update failed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(IoSession session, Object message) throws Exception
|
||||
{
|
||||
//Single-use session - close it after we receive a response
|
||||
session.closeNow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mSocketConnector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a song metadata update to the remote server. Additional metadata updates received while the updater
|
||||
* is in the process of sending an existing metadata update will be queued and processed in received order.
|
||||
@@ -126,66 +76,87 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
*/
|
||||
public void update(IdentifierCollection identifierCollection)
|
||||
{
|
||||
mMetadataQueue.offer(getSong(identifierCollection));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(!mUpdating.get() && !mMetadataQueue.isEmpty())
|
||||
try
|
||||
{
|
||||
Runnable runnable = new Runnable()
|
||||
sb.append("http://");
|
||||
sb.append(mIcecastConfiguration.getHost());
|
||||
sb.append(":");
|
||||
sb.append(mIcecastConfiguration.getPort());
|
||||
sb.append("/admin/metadata?mode=updinfo&mount=");
|
||||
sb.append(URLEncoder.encode(mIcecastConfiguration.getMountPoint(), UTF8));
|
||||
sb.append("&charset=UTF%2d8");
|
||||
sb.append("&song=").append(URLEncoder.encode(getSong(identifierCollection), UTF8));
|
||||
}
|
||||
catch(UnsupportedEncodingException uee)
|
||||
{
|
||||
mLog.error("Error encoding metadata information to UTF-8", uee);
|
||||
sb = null;
|
||||
}
|
||||
|
||||
if(sb != null)
|
||||
{
|
||||
final String metadataUpdateURL = sb.toString();
|
||||
URI uri = URI.create(metadataUpdateURL);
|
||||
|
||||
ThreadPool.SCHEDULED.submit(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!mMetadataQueue.isEmpty() && mUpdating.compareAndSet(false, true))
|
||||
try
|
||||
{
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(uri)
|
||||
.header(IcecastHeader.AUTHORIZATION.getValue(), mIcecastConfiguration.getBase64EncodedCredentials())
|
||||
.header(IcecastHeader.USER_AGENT.getValue(), SystemProperties.getInstance().getApplicationName())
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = null;
|
||||
|
||||
try
|
||||
{
|
||||
ConnectFuture connectFuture = getSocketConnector()
|
||||
.connect(new InetSocketAddress(mIcecastConfiguration.getHost(),
|
||||
mIcecastConfiguration.getPort()));
|
||||
connectFuture.awaitUninterruptibly();
|
||||
IoSession session = connectFuture.getSession();
|
||||
|
||||
if(session != null)
|
||||
response = mHttpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
}
|
||||
catch(IOException ioe)
|
||||
{
|
||||
if(!mConnectionLoggingSuppressed)
|
||||
{
|
||||
String song = mMetadataQueue.poll();
|
||||
mLog.error("IO Error submitting Icecast metadata update [" +
|
||||
(metadataUpdateURL != null ? metadataUpdateURL : "no url"), ioe);
|
||||
mConnectionLoggingSuppressed = true;
|
||||
}
|
||||
}
|
||||
catch(InterruptedException ie)
|
||||
{
|
||||
mLog.error("Interrupted Exception Error", ie);
|
||||
}
|
||||
|
||||
while(song != null)
|
||||
if(response != null)
|
||||
{
|
||||
if(response.statusCode() == 200)
|
||||
{
|
||||
mConnectionLoggingSuppressed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!mConnectionLoggingSuppressed)
|
||||
{
|
||||
HttpRequest updateRequest = createUpdateRequest(song);
|
||||
|
||||
if(updateRequest != null)
|
||||
{
|
||||
session.write(updateRequest);
|
||||
}
|
||||
|
||||
//Fetch next metadata update to send
|
||||
song = mMetadataQueue.poll();
|
||||
mLog.info("Error submitting Icecast 2 Metadata update to URL [" + metadataUpdateURL +
|
||||
"] HTTP Response Code [" + response.statusCode() + "] Body [" + response.body() + "]");
|
||||
mConnectionLoggingSuppressed = true;
|
||||
}
|
||||
|
||||
session.closeNow();
|
||||
}
|
||||
}
|
||||
catch(UnresolvedAddressException | RuntimeIoException ure)
|
||||
{
|
||||
//Do nothing - the server is temporarily unavailable
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Throwable throwableCause = e.getCause();
|
||||
|
||||
if(!mStackTraceLoggingSuppressed)
|
||||
{
|
||||
mLog.error("Error sending metadata update. Future errors will be suppressed", e);
|
||||
mStackTraceLoggingSuppressed = true;
|
||||
}
|
||||
}
|
||||
|
||||
mUpdating.set(false);
|
||||
}
|
||||
catch(Throwable t)
|
||||
{
|
||||
mLog.error("There was an error submitting an Icecast metadata update", t);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ThreadPool.SCHEDULED.schedule(runnable, 0l, TimeUnit.SECONDS);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,13 +178,22 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
|
||||
}
|
||||
|
||||
if(to == null)
|
||||
{
|
||||
List<Identifier> toIdentifiers = identifierCollection.getIdentifiers(Role.TO);
|
||||
if(!toIdentifiers.isEmpty())
|
||||
{
|
||||
to = toIdentifiers.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if(to != null)
|
||||
{
|
||||
sb.append("TO:").append(to);
|
||||
|
||||
List<Alias> aliases = aliasList.getAliases(to);
|
||||
|
||||
if(!aliases.isEmpty())
|
||||
if(aliases != null && !aliases.isEmpty())
|
||||
{
|
||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
}
|
||||
@@ -223,7 +203,17 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
sb.append("TO:UNKNOWN");
|
||||
}
|
||||
|
||||
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.FROM);
|
||||
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.RADIO, Role.FROM);
|
||||
|
||||
if(from == null)
|
||||
{
|
||||
List<Identifier> fromIdentifiers = identifierCollection.getIdentifiers(Role.FROM);
|
||||
|
||||
if(!fromIdentifiers.isEmpty())
|
||||
{
|
||||
from = fromIdentifiers.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if(from != null)
|
||||
{
|
||||
@@ -231,7 +221,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
|
||||
List<Alias> aliases = aliasList.getAliases(from);
|
||||
|
||||
if(!aliases.isEmpty())
|
||||
if(aliases != null && !aliases.isEmpty())
|
||||
{
|
||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
}
|
||||
@@ -248,46 +238,4 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an HTTP GET request to update the metadata on the remote server
|
||||
*/
|
||||
private HttpRequest createUpdateRequest(String song)
|
||||
{
|
||||
try
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("mode=updinfo");
|
||||
sb.append("&mount=").append(URLEncoder.encode(mIcecastConfiguration.getMountPoint(), UTF8));
|
||||
sb.append("&charset=UTF%2d8");
|
||||
sb.append("&song=").append(URLEncoder.encode(song, UTF8));
|
||||
|
||||
HttpRequestImpl request = new HttpRequestImpl(HttpVersion.HTTP_1_1, HttpMethod.GET, "/admin/metadata",
|
||||
sb.toString(), getHTTPHeaders());
|
||||
|
||||
return request;
|
||||
}
|
||||
catch(UnsupportedEncodingException e)
|
||||
{
|
||||
//This should never happen
|
||||
mLog.error("UTF-8 encoding is not supported - can't update song metadata");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP headers to use for a metadata update request.
|
||||
*/
|
||||
private Map<String,String> getHTTPHeaders()
|
||||
{
|
||||
if(mHTTPHeaders == null)
|
||||
{
|
||||
mHTTPHeaders = new HashMap<>();
|
||||
mHTTPHeaders.put(IcecastHeader.USER_AGENT.getValue(), SystemProperties.getInstance().getApplicationName());
|
||||
mHTTPHeaders.put(IcecastHeader.AUTHORIZATION.getValue(), mIcecastConfiguration.getBase64EncodedCredentials());
|
||||
}
|
||||
|
||||
return mHTTPHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast.shoutcast.v1;
|
||||
|
||||
@@ -203,6 +205,15 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
|
||||
}
|
||||
|
||||
if(to == null)
|
||||
{
|
||||
List<Identifier> toIdentifiers = identifierCollection.getIdentifiers(Role.TO);
|
||||
if(!toIdentifiers.isEmpty())
|
||||
{
|
||||
to = toIdentifiers.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if(to != null)
|
||||
{
|
||||
sb.append("TO:").append(to);
|
||||
@@ -219,7 +230,17 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
sb.append("TO:UNKNOWN");
|
||||
}
|
||||
|
||||
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.FROM);
|
||||
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.RADIO, Role.FROM);
|
||||
|
||||
if(from == null)
|
||||
{
|
||||
List<Identifier> fromIdentifiers = identifierCollection.getIdentifiers(Role.FROM);
|
||||
|
||||
if(!fromIdentifiers.isEmpty())
|
||||
{
|
||||
from = fromIdentifiers.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if(from != null)
|
||||
{
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast.shoutcast.v2;
|
||||
|
||||
@@ -278,6 +280,8 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
|
||||
if(identifierCollection != null)
|
||||
{
|
||||
StringBuilder sbTitle2 = new StringBuilder();
|
||||
|
||||
AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
|
||||
|
||||
Identifier to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.PATCH_GROUP, Role.TO);
|
||||
@@ -287,39 +291,61 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
|
||||
}
|
||||
|
||||
if(to == null)
|
||||
{
|
||||
List<Identifier> toIdentifiers = identifierCollection.getIdentifiers(Role.TO);
|
||||
|
||||
if(!toIdentifiers.isEmpty())
|
||||
{
|
||||
to = toIdentifiers.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if(to != null)
|
||||
{
|
||||
sb.append("TO:").append(to);
|
||||
sbTitle2.append("TO:").append(to);
|
||||
|
||||
List<Alias> aliases = aliasList.getAliases(to);
|
||||
|
||||
if(!aliases.isEmpty())
|
||||
{
|
||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
sbTitle2.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("TO:UNKNOWN");
|
||||
sbTitle2.append("TO:UNKNOWN");
|
||||
}
|
||||
|
||||
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.FROM);
|
||||
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.RADIO, Role.FROM);
|
||||
|
||||
if(from == null)
|
||||
{
|
||||
List<Identifier> fromIdentifiers = identifierCollection.getIdentifiers(Role.FROM);
|
||||
|
||||
if(!fromIdentifiers.isEmpty())
|
||||
{
|
||||
from = fromIdentifiers.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if(from != null)
|
||||
{
|
||||
sb.append(" FROM:").append(from);
|
||||
sbTitle2.append(" FROM:").append(from);
|
||||
|
||||
List<Alias> aliases = aliasList.getAliases(from);
|
||||
|
||||
if(!aliases.isEmpty())
|
||||
{
|
||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
sbTitle2.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(" FROM:UNKNOWN");
|
||||
sbTitle2.append(" FROM:UNKNOWN");
|
||||
}
|
||||
|
||||
sb.append(UltravoxMetadata.TITLE_2.asXML(sbTitle2.toString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -69,4 +69,11 @@ public class SquelchStateEvent
|
||||
{
|
||||
return new SquelchStateEvent(squelchState, timeslot);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Squelch Event - State:").append(mSquelchState).append(" Timeslot:").append(mTimeslot);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
/*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.bits;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
@@ -94,8 +100,8 @@ public class MultiSyncPatternMatcher
|
||||
|
||||
if(mBitCount > mSyncLossThreshold)
|
||||
{
|
||||
mSyncDetectListener.syncLost(mBitCount);
|
||||
mBitCount = 0;
|
||||
mSyncDetectListener.syncLost();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -261,7 +261,12 @@ public class ChannelMetadata implements Listener<IdentifierUpdateNotification>,
|
||||
@Override
|
||||
public void receive(IdentifierUpdateNotification update)
|
||||
{
|
||||
// mLog.debug("Received update: " + update + " class:" + update.getIdentifier().getClass());
|
||||
// mLog.debug("Received update: " + update +
|
||||
// " class:" + update.getIdentifier().getIdentifierClass() +
|
||||
// " form:" + update.getIdentifier().getForm() +
|
||||
// " role:" + update.getIdentifier().getRole() +
|
||||
// " class:" + update.getIdentifier().getClass());
|
||||
|
||||
Identifier identifier = update.getIdentifier();
|
||||
|
||||
switch(identifier.getIdentifierClass())
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -199,7 +199,8 @@ public class ChannelMetadataModel extends AbstractTableModel implements IChannel
|
||||
}
|
||||
else
|
||||
{
|
||||
return id.getValue() + " TS:" + channelMetadata.getTimeslot();
|
||||
String value = id.getValue().replace(" TS0", "").replace(" TS1", "");
|
||||
return value + " TS:" + channelMetadata.getTimeslot();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -47,6 +47,7 @@ import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
|
||||
import io.github.dsheirer.source.Source;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import io.github.dsheirer.source.SourceException;
|
||||
import io.github.dsheirer.source.SourceManager;
|
||||
import org.slf4j.Logger;
|
||||
@@ -262,6 +263,30 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
||||
processingChain.addDecodeEventListener(listener);
|
||||
}
|
||||
|
||||
//Add a listener to detect source error state that indicates the channel should be shutdown
|
||||
processingChain.addSourceEventListener(sourceEvent ->
|
||||
{
|
||||
if(sourceEvent.getEvent() == SourceEvent.Event.NOTIFICATION_ERROR_STATE && sourceEvent.getSource() != null)
|
||||
{
|
||||
Channel toShutdown = null;
|
||||
|
||||
for(Map.Entry<Channel,ProcessingChain> entry: mProcessingChains.entrySet())
|
||||
{
|
||||
if(entry.getValue().hasSource(sourceEvent.getSource()))
|
||||
{
|
||||
toShutdown = entry.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(toShutdown != null)
|
||||
{
|
||||
mLog.info("Channel source error detected - stopping channel [" + toShutdown.getName() + "]");
|
||||
stopProcessing(toShutdown, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//Register this manager to receive channel events from traffic channel manager modules within
|
||||
//the processing chain
|
||||
processingChain.addChannelEventListener(this);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -126,6 +126,18 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
this(tunerController, tunerController.getFrequency(), tunerController.getSampleRate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals to all provisioned tuner channel sources that the source complex buffer provider has an error and can
|
||||
* no longer provide channels, so that the tuner channel source can notify the consumer of the error state.
|
||||
*/
|
||||
public void setErrorMessage(String errorMessage)
|
||||
{
|
||||
for(TunerChannelSource tunerChannelSource: mChannelSources)
|
||||
{
|
||||
tunerChannelSource.setError(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Current channel sample rate which is (2 * channel bandwidth).
|
||||
*/
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.dsp.fsk;
|
||||
|
||||
@@ -139,7 +141,7 @@ public class LTRDecoder implements Listener<ReusableFloatBuffer>, ISyncDetectLis
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
/*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.dsp.fsk;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
@@ -129,7 +135,7 @@ public class SynchronizationMonitor implements ISyncDetectListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
package io.github.dsheirer.dsp.psk.pll;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
import io.github.dsheirer.module.decode.FeedbackDecoder;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Monitors decode sync events to adaptively control PLL loop gain.
|
||||
*/
|
||||
public class AdaptivePLLBandwidthMonitor implements ISyncDetectListener, IFrequencyErrorProcessor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(AdaptivePLLBandwidthMonitor.class);
|
||||
|
||||
private static final int MAX_SYNC_COUNT = PLLBandwidth.BW_200.getRangeEnd();
|
||||
private CostasLoop mCostasLoop;
|
||||
private FeedbackDecoder mFeedbackDecoder;
|
||||
private PLLBandwidth mPLLBandwidth = PLLBandwidth.BW_400;
|
||||
private int mSyncCount;
|
||||
|
||||
/**
|
||||
* Constructs an adaptive monitor to monitor the sync state of a decoder and adjust the gain
|
||||
* level of the costas loop accordingly.
|
||||
*
|
||||
* @param costasLoop to receive adaptive gain updates.
|
||||
* @param feedbackDecoder to rebroadcast frequency error source events
|
||||
*/
|
||||
public AdaptivePLLBandwidthMonitor(CostasLoop costasLoop, FeedbackDecoder feedbackDecoder)
|
||||
{
|
||||
mCostasLoop = costasLoop;
|
||||
mCostasLoop.setPLLBandwidth(mPLLBandwidth);
|
||||
mCostasLoop.setFrequencyErrorProcessor(this);
|
||||
mFeedbackDecoder = feedbackDecoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync detection event. Updates the running sync count and updates the PLL gain level.
|
||||
*/
|
||||
@Override
|
||||
public void syncDetected(int bitErrors)
|
||||
{
|
||||
mSyncCount++;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync loss event. Updates the running sync count and updates the PLL gain level.
|
||||
*/
|
||||
@Override
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
mSyncCount -= 2;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the gain state for a sync detect or sync loss
|
||||
*/
|
||||
private void update()
|
||||
{
|
||||
if(mSyncCount < 0)
|
||||
{
|
||||
mSyncCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(mSyncCount > MAX_SYNC_COUNT)
|
||||
{
|
||||
mSyncCount = MAX_SYNC_COUNT;
|
||||
return;
|
||||
}
|
||||
|
||||
PLLBandwidth gain = PLLBandwidth.fromSyncCount(mSyncCount);
|
||||
|
||||
//Only update the costas loop if the gain value changes
|
||||
if(gain != mPLLBandwidth)
|
||||
{
|
||||
mPLLBandwidth = gain;
|
||||
mCostasLoop.setPLLBandwidth(mPLLBandwidth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the monitor and commands the PLL to use the highest gain level.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
mSyncCount = 0;
|
||||
mPLLBandwidth = PLLBandwidth.BW_400;
|
||||
mCostasLoop.setPLLBandwidth(mPLLBandwidth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processFrequencyError(long frequencyError)
|
||||
{
|
||||
//Only rebroadcast the costas loop frequency error if the gain level has progressed above
|
||||
//a bandwidth of 300, meaning that we have received at least 4 sync events
|
||||
if(mPLLBandwidth != PLLBandwidth.BW_400 && mPLLBandwidth != PLLBandwidth.BW_300)
|
||||
{
|
||||
mFeedbackDecoder.broadcast(SourceEvent.frequencyErrorMeasurement(frequencyError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.dsp.psk.pll;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Monitors decode sync events to adaptively control PLL loop gain.
|
||||
*/
|
||||
public class AdaptivePLLGainMonitor implements ISyncDetectListener, IFrequencyErrorProcessor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(AdaptivePLLGainMonitor.class);
|
||||
|
||||
private static final int MAX_SYNC_COUNT = 6;
|
||||
private CostasLoop mCostasLoop;
|
||||
private P25P1Decoder mP25P1Decoder;
|
||||
private PLLGain mPLLGain = PLLGain.LEVEL_1;
|
||||
private int mSyncCount;
|
||||
|
||||
/**
|
||||
* Constructs an adaptive monitor to monitor the sync state of a decoder and adjust the gain
|
||||
* level of the costas loop accordingly.
|
||||
*
|
||||
* @param costasLoop to receive adaptive gain updates.
|
||||
* @param p25P1Decoder to receive frequency error source events
|
||||
*/
|
||||
public AdaptivePLLGainMonitor(CostasLoop costasLoop, P25P1Decoder p25P1Decoder)
|
||||
{
|
||||
mCostasLoop = costasLoop;
|
||||
mCostasLoop.setPLLGain(mPLLGain);
|
||||
mCostasLoop.setFrequencyErrorProcessor(this);
|
||||
mP25P1Decoder = p25P1Decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync detection event. Updates the running sync count and updates the PLL gain level.
|
||||
*/
|
||||
@Override
|
||||
public void syncDetected(int bitErrors)
|
||||
{
|
||||
mSyncCount++;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync loss event. Updates the running sync count and updates the PLL gain level.
|
||||
*/
|
||||
@Override
|
||||
public void syncLost()
|
||||
{
|
||||
mSyncCount -= 2;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the gain state for a sync detect or sync loss
|
||||
*/
|
||||
private void update()
|
||||
{
|
||||
if(mSyncCount < 0)
|
||||
{
|
||||
mSyncCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(mSyncCount > MAX_SYNC_COUNT)
|
||||
{
|
||||
mSyncCount = MAX_SYNC_COUNT;
|
||||
return;
|
||||
}
|
||||
|
||||
PLLGain gain = PLLGain.fromSyncCount(mSyncCount);
|
||||
|
||||
//Only update the costas loop if the gain value changes
|
||||
if(gain != mPLLGain)
|
||||
{
|
||||
mPLLGain = gain;
|
||||
mCostasLoop.setPLLGain(mPLLGain);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the monitor and commands the PLL to use the highest gain level.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
mSyncCount = 0;
|
||||
mPLLGain = PLLGain.LEVEL_1;
|
||||
mCostasLoop.setPLLGain(mPLLGain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processFrequencyError(long frequencyError)
|
||||
{
|
||||
//Only rebroadcast the costas loop frequency error if the gain level has progressed above the
|
||||
//default gain of 1, meaning that we have received at least 2 sync events
|
||||
if(mPLLGain != PLLGain.LEVEL_1)
|
||||
{
|
||||
mP25P1Decoder.broadcast(SourceEvent.frequencyErrorMeasurement(frequencyError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
/*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.dsp.psk.pll;
|
||||
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
@@ -41,7 +47,7 @@ public class CostasLoop implements IPhaseLockedLoop
|
||||
private double mDamping = Math.sqrt(2.0) / 2.0;
|
||||
private double mAlphaGain;
|
||||
private double mBetaGain;
|
||||
private PLLGain mPLLGain = PLLGain.LEVEL_1;
|
||||
private PLLBandwidth mPLLBandwidth = PLLBandwidth.BW_400;
|
||||
private double mSymbolRate;
|
||||
private double mSampleRate;
|
||||
private IFrequencyErrorProcessor mFrequencyErrorProcessor;
|
||||
@@ -63,8 +69,7 @@ public class CostasLoop implements IPhaseLockedLoop
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the listener to receive the measured frequency error as tracked by the PLL at one
|
||||
* second intervals.
|
||||
* Registers the listener to receive the measured frequency error as tracked by the PLL once per second
|
||||
*
|
||||
* @param listener to receive frequency error measurement.
|
||||
*/
|
||||
@@ -102,22 +107,25 @@ public class CostasLoop implements IPhaseLockedLoop
|
||||
*/
|
||||
private void updateLoopBandwidth()
|
||||
{
|
||||
double bandwidth = TWO_PI / mPLLGain.getLoopBandwidth();
|
||||
double bandwidth = TWO_PI / mPLLBandwidth.getLoopBandwidth();
|
||||
|
||||
mAlphaGain = (4.0 * mDamping * bandwidth) / (1.0 + (2.0 * mDamping * bandwidth) + (bandwidth * bandwidth));
|
||||
mBetaGain = (4.0 * bandwidth * bandwidth) / (1.0 + (2.0 * mDamping * bandwidth) + (bandwidth * bandwidth));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the PLLGain state for this costas loop. The PLLGain state affects the aggressiveness of the alpha/beta
|
||||
* Sets the PLLBandwidth state for this costas loop. The bandwidth affects the aggressiveness of the alpha/beta
|
||||
* gain values in synchronizing with the signal carrier.
|
||||
*
|
||||
* @param PLLGain
|
||||
* @param pllBandwidth
|
||||
*/
|
||||
public void setPLLGain(PLLGain PLLGain)
|
||||
public void setPLLBandwidth(PLLBandwidth pllBandwidth)
|
||||
{
|
||||
mPLLGain = PLLGain;
|
||||
updateLoopBandwidth();
|
||||
if(mPLLBandwidth != pllBandwidth)
|
||||
{
|
||||
mPLLBandwidth = pllBandwidth;
|
||||
updateLoopBandwidth();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,8 +170,7 @@ public class CostasLoop implements IPhaseLockedLoop
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the costas loop frequency and phase to adjust for the phase
|
||||
* error value
|
||||
* Updates the costas loop frequency and phase to adjust for the phase error value
|
||||
*
|
||||
* @param phaseError - (-)= late and (+)= early
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
package io.github.dsheirer.dsp.psk.pll;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
import io.github.dsheirer.module.decode.FeedbackDecoder;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Monitors decode sync events to adaptively control frequency correction broadcasts.
|
||||
*/
|
||||
public class FrequencyCorrectionSyncMonitor implements ISyncDetectListener, IFrequencyErrorProcessor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(FrequencyCorrectionSyncMonitor.class);
|
||||
|
||||
private static final int MAX_SYNC_COUNT = PLLBandwidth.BW_200.getRangeEnd();
|
||||
private FeedbackDecoder mFeedbackDecoder;
|
||||
private CostasLoop mCostasLoop;
|
||||
private int mSyncCount;
|
||||
|
||||
/**
|
||||
* Constructs an adaptive monitor to monitor the sync state of a decoder
|
||||
*
|
||||
* @param costasLoop to receive adaptive gain updates.
|
||||
* @param feedbackDecoder to rebroadcast frequency error source events
|
||||
*/
|
||||
public FrequencyCorrectionSyncMonitor(CostasLoop costasLoop, FeedbackDecoder feedbackDecoder)
|
||||
{
|
||||
mCostasLoop = costasLoop;
|
||||
mCostasLoop.setFrequencyErrorProcessor(this);
|
||||
mFeedbackDecoder = feedbackDecoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync detection event. Updates the running sync count and updates the PLL gain level.
|
||||
*/
|
||||
@Override
|
||||
public void syncDetected(int bitErrors)
|
||||
{
|
||||
mSyncCount++;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync loss event. Updates the running sync count and updates the PLL gain level.
|
||||
*/
|
||||
@Override
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
mSyncCount -= 2;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sync count
|
||||
*/
|
||||
private void update()
|
||||
{
|
||||
if(mSyncCount < 0)
|
||||
{
|
||||
mSyncCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(mSyncCount > MAX_SYNC_COUNT)
|
||||
{
|
||||
mSyncCount = MAX_SYNC_COUNT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the monitor
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
mSyncCount = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processFrequencyError(long frequencyError)
|
||||
{
|
||||
//Only rebroadcast the frequency error if the sync count is more than 2
|
||||
if(mSyncCount > 2)
|
||||
{
|
||||
mFeedbackDecoder.broadcast(SourceEvent.frequencyErrorMeasurement(frequencyError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -21,37 +21,45 @@
|
||||
*/
|
||||
package io.github.dsheirer.dsp.psk.pll;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Phase Locked Loop (PLL) tracking bandwidth - controls how fast/slow the PLL tracks the carrier frequency
|
||||
*/
|
||||
public enum PLLGain
|
||||
public enum PLLBandwidth
|
||||
{
|
||||
//NOTE: static gain level of 200 produced the best results for releases prior to 0.3.4b2
|
||||
//NOTE: static bandwidth of 200 produced the best results for P25P1 releases prior to 0.3.4b2
|
||||
|
||||
LEVEL_0(100.0, 0, 0),
|
||||
LEVEL_1(150.0, 0, 1),
|
||||
LEVEL_2(170.0, 2, 4),
|
||||
LEVEL_3(190.0, 5, 6),
|
||||
LEVEL_4(200.0, 7, 8),
|
||||
LEVEL_5(200.0, 9, 10),
|
||||
LEVEL_6(250.0, 11, 12),
|
||||
LEVEL_7(275.0, 12,13),
|
||||
LEVEL_8(325.0, 14, 15),
|
||||
LEVEL_9(350.0, 16,17),
|
||||
LEVEL_10(375.0, 18, 19),
|
||||
LEVEL_11(400.0, 19,20);
|
||||
BW_400(400.0, 0, 1),
|
||||
BW_300(300.0, 2, 3),
|
||||
BW_250(250.0, 4, 5),
|
||||
BW_200(200.0, 6, 7);
|
||||
|
||||
private double mLoopBandwidth;
|
||||
private int mRangeStart;
|
||||
private int mRangeEnd;
|
||||
|
||||
PLLGain(double loopBandwidth, int start, int end)
|
||||
PLLBandwidth(double loopBandwidth, int start, int end)
|
||||
{
|
||||
mLoopBandwidth = loopBandwidth;
|
||||
mRangeStart = start;
|
||||
mRangeEnd = end;
|
||||
}
|
||||
|
||||
private static Map<Integer,PLLBandwidth> LOOKUP_MAP = new TreeMap<>();
|
||||
|
||||
static
|
||||
{
|
||||
for(PLLBandwidth pllBandwidth : PLLBandwidth.values())
|
||||
{
|
||||
for(int x = pllBandwidth.getRangeStart(); x <= pllBandwidth.getRangeEnd(); x++)
|
||||
{
|
||||
LOOKUP_MAP.put(x, pllBandwidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop bandwidth setting
|
||||
*/
|
||||
@@ -76,27 +84,13 @@ public enum PLLGain
|
||||
* @param syncCount 0-10
|
||||
* @return PLL gain appropriate for the sync detection value
|
||||
*/
|
||||
public static PLLGain fromSyncCount(int syncCount)
|
||||
public static PLLBandwidth fromSyncCount(int syncCount)
|
||||
{
|
||||
if(syncCount <= LEVEL_1.getRangeEnd())
|
||||
if(LOOKUP_MAP.containsKey(syncCount))
|
||||
{
|
||||
return LEVEL_1;
|
||||
}
|
||||
else if(syncCount <= LEVEL_2.getRangeEnd())
|
||||
{
|
||||
return LEVEL_2;
|
||||
}
|
||||
else if(syncCount <= LEVEL_3.getRangeEnd())
|
||||
{
|
||||
return LEVEL_3;
|
||||
}
|
||||
else if(syncCount <= LEVEL_4.getRangeEnd())
|
||||
{
|
||||
return LEVEL_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LEVEL_5;
|
||||
return LOOKUP_MAP.get(syncCount);
|
||||
}
|
||||
|
||||
return BW_200;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.dsp.psk.pll;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.Dibit;
|
||||
|
||||
/**
|
||||
* Utility for calculating phase inverted sync pattern derivatives for QPSK constellations
|
||||
*/
|
||||
public class QPSKPhaseInversionCalculator
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
|
||||
//DMR sync patterns
|
||||
// String[] syncs = {"755FD7DF75F7", "DFF57D75DF5D", "7F7D5DD57DFD", "D5D7F77FD757", "77D55F7DFD77",
|
||||
// "5D577F7757FF", "F7FDD5DDFD55", "7DFFD5F55D5F", "D7557F5FF7F5", "DD7FF5D757DD"};
|
||||
|
||||
//P25 Phase 2 sync pattern
|
||||
String[] syncs = {"575D57F7FF"};
|
||||
|
||||
//P25 Phase 1 sync pattern
|
||||
// String[] syncs = {"5575F5FF77FF"};
|
||||
|
||||
|
||||
for(String sync: syncs)
|
||||
{
|
||||
StringBuilder sbNorm = new StringBuilder();
|
||||
StringBuilder sbP90 = new StringBuilder();
|
||||
StringBuilder sbM90 = new StringBuilder();
|
||||
StringBuilder sb180 = new StringBuilder();
|
||||
|
||||
for(char letter: sync.toCharArray())
|
||||
{
|
||||
int value;
|
||||
|
||||
if(Character.isAlphabetic(letter))
|
||||
{
|
||||
value = letter - 55;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = letter - 48;
|
||||
}
|
||||
|
||||
sbNorm.append(letter);
|
||||
sbP90.append(rotate(value, Dibit.Rotation.PLUS90));
|
||||
sbM90.append(rotate(value, Dibit.Rotation.MINUS90));
|
||||
sb180.append(rotate(value, Dibit.Rotation.INVERT));
|
||||
}
|
||||
|
||||
System.out.println("NORMAL: " + sync);
|
||||
System.out.println(" +90: " + sbP90.toString());
|
||||
System.out.println(" -90: " + sbM90.toString());
|
||||
System.out.println(" 180: " + sb180.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the hexadecimal value to an integer, decomposes it into high and low order dibits, rotates the dibits
|
||||
* in the specified direction, and recombines the rotated dibits into a 4-bit value, returned as a hex character.
|
||||
* @param value to rotate
|
||||
* @param direction direction
|
||||
* @return rotated hex character
|
||||
*/
|
||||
public static String rotate(int value, Dibit.Rotation direction)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dibit dibitHigh = getHighDibit(value);
|
||||
Dibit dibitLow = getLowDibit(value);
|
||||
return getHex(dibitHigh.rotate(direction), dibitLow.rotate(direction));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
//ignore
|
||||
}
|
||||
|
||||
return "-";
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the bit values from the two dibits and converts the integer value to a hex character
|
||||
* @param d1 containing the high order bits
|
||||
* @param d2 containing the low order bits
|
||||
* @return string hex character representing the value of these dibits combined
|
||||
*/
|
||||
public static String getHex(Dibit d1, Dibit d2)
|
||||
{
|
||||
int value = d1.getHighValue() + d2.getLowValue();
|
||||
return Integer.toHexString(value).toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the dibit that represents the bits in the 0x8 and 0x4 bit positions of the value
|
||||
* @param value
|
||||
* @return a dibit
|
||||
*/
|
||||
public static Dibit getHighDibit(int value)
|
||||
{
|
||||
return Dibit.fromValue((value >> 2) & 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the dibit that represents the bits in the 0x2 and 0x1 bit positions of the value
|
||||
* @param value
|
||||
* @return a dibit
|
||||
*/
|
||||
public static Dibit getLowDibit(int value)
|
||||
{
|
||||
return Dibit.fromValue(value & 3);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,25 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.dsp.symbol;
|
||||
|
||||
public enum Dibit
|
||||
@@ -133,6 +155,89 @@ public enum Dibit
|
||||
return Dibit.D00_PLUS_1;
|
||||
}
|
||||
|
||||
public static enum Rotation {PLUS90, MINUS90, INVERT}
|
||||
|
||||
/**
|
||||
* Returns the value of this dibit if the symbol were rotated in the direction indicated.
|
||||
*
|
||||
* This can be used for calculating phase rotation and phase inversion pattern derivatives from a normal sync pattern
|
||||
* @param rotation to apply to this dibit
|
||||
* @return rotated version of this dibit
|
||||
*/
|
||||
public Dibit rotate(Rotation rotation)
|
||||
{
|
||||
switch(this)
|
||||
{
|
||||
case D00_PLUS_1:
|
||||
switch(rotation)
|
||||
{
|
||||
case PLUS90:
|
||||
return Dibit.D01_PLUS_3;
|
||||
case MINUS90:
|
||||
return Dibit.D10_MINUS_1;
|
||||
case INVERT:
|
||||
return Dibit.D11_MINUS_3;
|
||||
}
|
||||
break;
|
||||
case D01_PLUS_3:
|
||||
switch(rotation)
|
||||
{
|
||||
case PLUS90:
|
||||
return Dibit.D11_MINUS_3;
|
||||
case MINUS90:
|
||||
return Dibit.D00_PLUS_1;
|
||||
case INVERT:
|
||||
return Dibit.D10_MINUS_1;
|
||||
}
|
||||
break;
|
||||
case D10_MINUS_1:
|
||||
switch(rotation)
|
||||
{
|
||||
case PLUS90:
|
||||
return Dibit.D00_PLUS_1;
|
||||
case MINUS90:
|
||||
return Dibit.D11_MINUS_3;
|
||||
case INVERT:
|
||||
return Dibit.D01_PLUS_3;
|
||||
}
|
||||
break;
|
||||
case D11_MINUS_3:
|
||||
switch(rotation)
|
||||
{
|
||||
case PLUS90:
|
||||
return Dibit.D10_MINUS_1;
|
||||
case MINUS90:
|
||||
return Dibit.D01_PLUS_3;
|
||||
case INVERT:
|
||||
return Dibit.D00_PLUS_1;
|
||||
}
|
||||
}
|
||||
|
||||
//We should never reach this point
|
||||
return Dibit.D00_PLUS_1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dibit that corresponds to the value
|
||||
* @param value 0-3
|
||||
* @return representative dibit or Dibit.00 if the value is outside of the range 0-3
|
||||
*/
|
||||
public static Dibit fromValue(int value)
|
||||
{
|
||||
switch(value)
|
||||
{
|
||||
case 0:
|
||||
default:
|
||||
return Dibit.D00_PLUS_1;
|
||||
case 1:
|
||||
return Dibit.D01_PLUS_3;
|
||||
case 2:
|
||||
return Dibit.D10_MINUS_1;
|
||||
case 3:
|
||||
return Dibit.D11_MINUS_3;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
byte a = (byte)0x1B;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -29,7 +29,10 @@ public enum FrameSync
|
||||
P25_PHASE1_ERROR_90_CW( 0x001050551155l ),
|
||||
P25_PHASE1_ERROR_180( 0xAA8A0A008800l ),
|
||||
|
||||
P25_PHASE2_NORMAL(0x575D57F7FFl);
|
||||
P25_PHASE2_NORMAL( 0x575D57F7FFl),
|
||||
P25_PHASE2_ERROR_90_CCW(0xFEFBFEAEAAl),
|
||||
P25_PHASE2_ERROR_90_CW( 0x0104015155l),
|
||||
P25_PHASE2_ERROR_180( 0xA8A2A80800l);
|
||||
|
||||
private long mSync;
|
||||
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
/*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.dsp.symbol;
|
||||
|
||||
/**
|
||||
@@ -31,6 +37,8 @@ public interface ISyncDetectListener
|
||||
|
||||
/**
|
||||
* Indicates that sync has been lost
|
||||
*
|
||||
* @param bitsProcessed number of bits that were processed without a sync detection
|
||||
*/
|
||||
void syncLost();
|
||||
void syncLost(int bitsProcessed);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -178,7 +178,7 @@ public class SDRTrunk implements Listener<TunerEvent>
|
||||
|
||||
ChannelMapModel channelMapModel = new ChannelMapModel();
|
||||
|
||||
EventLogManager eventLogManager = new EventLogManager(mUserPreferences);
|
||||
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
|
||||
|
||||
RecorderManager recorderManager = new RecorderManager(aliasModel, mUserPreferences);
|
||||
|
||||
@@ -474,7 +474,6 @@ public class SDRTrunk implements Listener<TunerEvent>
|
||||
mAudioPacketManager.stop();
|
||||
mLog.info("Stopping spectral display ...");
|
||||
mSpectralPanel.clearTuner();
|
||||
mLog.info("Releasing tuners ...");
|
||||
mSourceManager.shutdown();
|
||||
mLog.info("Shutdown complete.");
|
||||
mApplicationLog.stop();
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
/*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.gui.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
@@ -46,7 +52,7 @@ public class LJ1200Pane extends AbstractAFSK1200Pane
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
@@ -60,7 +66,7 @@ public class LJ1200Pane extends AbstractAFSK1200Pane
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
/*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.gui.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
@@ -46,7 +52,7 @@ public class MDC1200Pane extends AbstractAFSK1200Pane
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
mLog.debug("Sync Lost!");
|
||||
}
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
/*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.gui.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
@@ -46,7 +52,7 @@ public class MPT1327Pane extends AbstractAFSK1200Pane
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
@@ -60,7 +66,7 @@ public class MPT1327Pane extends AbstractAFSK1200Pane
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
/*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.gui.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
@@ -46,7 +52,7 @@ public class Tait1200Pane extends AbstractAFSK1200Pane
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -60,7 +66,7 @@ public class Tait1200Pane extends AbstractAFSK1200Pane
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.preference;
|
||||
@@ -30,7 +32,7 @@ public enum PreferenceEditorType
|
||||
DIRECTORY("Directories"),
|
||||
SOURCE_CHANNEL_MULTIPLE_FREQUENCY("Channel - Multiple Frequency"),
|
||||
SOURCE_TUNER_CHANNELIZER("Tuner Channelizer"),
|
||||
TALKGROUP_FORMAT("Talkgroups");
|
||||
TALKGROUP_FORMAT("Talkgroup & Radio ID");
|
||||
|
||||
private String mLabel;
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ public class Icon implements Comparable<Icon>
|
||||
{
|
||||
try
|
||||
{
|
||||
if(mPath.startsWith("/"))
|
||||
if(!mPath.startsWith("images"))
|
||||
{
|
||||
mImageIcon = new ImageIcon(mPath);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ public enum Form
|
||||
NEIGHBOR_SITE,
|
||||
NETWORK_ACCESS_CODE,
|
||||
PATCH_GROUP,
|
||||
RADIO,
|
||||
RF_SUBSYSTEM,
|
||||
SCRAMBLE_PARAMETERS,
|
||||
SHORT_DATA_MESSAGE,
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.identifier.patch;
|
||||
@@ -45,17 +47,17 @@ public class PatchGroup
|
||||
|
||||
public void addPatchedGroup(TalkgroupIdentifier patchedGroupIdentifier)
|
||||
{
|
||||
mPatchedGroupIdentifiers.add(patchedGroupIdentifier);
|
||||
if(!mPatchedGroupIdentifiers.contains(patchedGroupIdentifier))
|
||||
{
|
||||
mPatchedGroupIdentifiers.add(patchedGroupIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
public void addPatchedGroups(List<TalkgroupIdentifier> patchedGroupIdentifiers)
|
||||
{
|
||||
for(TalkgroupIdentifier identifier : patchedGroupIdentifiers)
|
||||
{
|
||||
if(!mPatchedGroupIdentifiers.contains(identifier))
|
||||
{
|
||||
mPatchedGroupIdentifiers.add(identifier);
|
||||
}
|
||||
addPatchedGroup(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.identifier.radio;
|
||||
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
|
||||
/**
|
||||
* Fully qualified radio identifier
|
||||
*/
|
||||
public abstract class FullyQualifiedRadioIdentifier extends RadioIdentifier
|
||||
{
|
||||
private int mWacn;
|
||||
private int mSystem;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param wacn
|
||||
* @param system
|
||||
* @param id
|
||||
*/
|
||||
public FullyQualifiedRadioIdentifier(int wacn, int system, int id, Role role)
|
||||
{
|
||||
super(id, role);
|
||||
mWacn = wacn;
|
||||
mSystem = system;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mWacn + "." + mSystem + "." + super.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.identifier.radio;
|
||||
|
||||
import io.github.dsheirer.identifier.Form;
|
||||
import io.github.dsheirer.identifier.IdentifierClass;
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.integer.IntegerIdentifier;
|
||||
|
||||
public abstract class RadioIdentifier extends IntegerIdentifier
|
||||
{
|
||||
public RadioIdentifier(Integer value, Role role)
|
||||
{
|
||||
super(value, IdentifierClass.USER, Form.RADIO, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return getValue() > 0;
|
||||
}
|
||||
}
|
||||
@@ -22,14 +22,15 @@
|
||||
|
||||
package io.github.dsheirer.identifier.talkgroup;
|
||||
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
|
||||
/**
|
||||
* Fully qualified radio identifier
|
||||
*/
|
||||
public class FullyQualifiedIdentifier
|
||||
public abstract class FullyQualifiedTalkgroupIdentifier extends TalkgroupIdentifier
|
||||
{
|
||||
private int mWacn;
|
||||
private int mSystem;
|
||||
private int mId;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
@@ -37,28 +38,16 @@ public class FullyQualifiedIdentifier
|
||||
* @param system
|
||||
* @param id
|
||||
*/
|
||||
public FullyQualifiedIdentifier(int wacn, int system, int id)
|
||||
public FullyQualifiedTalkgroupIdentifier(int wacn, int system, int id, Role role)
|
||||
{
|
||||
super(id, role);
|
||||
mWacn = wacn;
|
||||
mSystem = system;
|
||||
mId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mWacn + "." + mSystem + "." + mId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance with the specified values
|
||||
* @param wacn value
|
||||
* @param system value
|
||||
* @param id value
|
||||
* @return instance
|
||||
*/
|
||||
public static FullyQualifiedIdentifier create(int wacn, int system, int id)
|
||||
{
|
||||
return new FullyQualifiedIdentifier(wacn, system, id);
|
||||
return mWacn + "." + mSystem + "." + super.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.identifier.talkgroup;
|
||||
@@ -30,7 +32,7 @@ public class LTRTalkgroup extends TalkgroupIdentifier implements Comparable<LTRT
|
||||
{
|
||||
public LTRTalkgroup(Integer talkgroup, Role role)
|
||||
{
|
||||
super(talkgroup, role, true);
|
||||
super(talkgroup, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.identifier.talkgroup;
|
||||
@@ -27,12 +29,9 @@ import io.github.dsheirer.identifier.integer.IntegerIdentifier;
|
||||
|
||||
public abstract class TalkgroupIdentifier extends IntegerIdentifier
|
||||
{
|
||||
private boolean mIsGroup;
|
||||
|
||||
public TalkgroupIdentifier(Integer value, Role role, boolean isGroup)
|
||||
public TalkgroupIdentifier(Integer value, Role role)
|
||||
{
|
||||
super(value, IdentifierClass.USER, Form.TALKGROUP, role);
|
||||
mIsGroup = isGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,12 +39,4 @@ public abstract class TalkgroupIdentifier extends IntegerIdentifier
|
||||
{
|
||||
return getValue() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is a group or individual identifier
|
||||
*/
|
||||
public boolean isGroup()
|
||||
{
|
||||
return mIsGroup;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
package io.github.dsheirer.message;
|
||||
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Empty message to convey that a number of stuff/tail bits were processed with no sync or valid message detected.
|
||||
*
|
||||
* This message supports periodic updates to external processor(s) that may be tracking bit error rates.
|
||||
*/
|
||||
public class StuffBitsMessage extends Message
|
||||
{
|
||||
private int mBitsProcessed;
|
||||
private Protocol mProtocol;
|
||||
|
||||
/**
|
||||
* Constructs a sync loss message.
|
||||
*
|
||||
* @param timestamp of the message
|
||||
* @param bitsProcessed without a sync pattern detection of message decode
|
||||
*/
|
||||
public StuffBitsMessage(long timestamp, int bitsProcessed, Protocol protocol)
|
||||
{
|
||||
super(timestamp);
|
||||
mBitsProcessed = bitsProcessed;
|
||||
mProtocol = protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the number of bits that were processed without a sync dectection or message decode
|
||||
*/
|
||||
public int getBitsProcessed()
|
||||
{
|
||||
return mBitsProcessed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "<-> TAIL/STUFF BITS PROCESSED [" + getBitsProcessed() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Protocol getProtocol()
|
||||
{
|
||||
return mProtocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -115,14 +115,12 @@ public class ProcessingChain implements Listener<ChannelEvent>
|
||||
private Broadcaster<SourceEvent> mSourceEventBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<IMessage> mMessageBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<SquelchStateEvent> mSquelchStateEventBroadcaster = new Broadcaster<>();
|
||||
|
||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||
|
||||
protected Source mSource;
|
||||
private List<Module> mModules = new ArrayList<>();
|
||||
private DecodeEventModel mDecodeEventModel;
|
||||
private AbstractChannelState mChannelState;
|
||||
private MessageActivityModel mMessageActivityModel;
|
||||
protected Source mSource;
|
||||
|
||||
/**
|
||||
* Creates a processing chain for managing a set of modules
|
||||
@@ -208,6 +206,14 @@ public class ProcessingChain implements Listener<ChannelEvent>
|
||||
return mSource != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this chain's source is the same as the source argument
|
||||
*/
|
||||
public boolean hasSource(Source source)
|
||||
{
|
||||
return mSource != null && mSource.equals(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a sample source to this processing chain. Processing won't
|
||||
* start until the start() method is invoked.
|
||||
@@ -800,6 +806,14 @@ public class ProcessingChain implements Listener<ChannelEvent>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to receive source events from this processing chain
|
||||
*/
|
||||
public void addSourceEventListener(Listener<SourceEvent> listener)
|
||||
{
|
||||
mSourceEventBroadcaster.addListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the listener from receiving decoded messages from all decoders.
|
||||
*/
|
||||
|
||||
@@ -38,7 +38,7 @@ public enum DecoderType
|
||||
NBFM("NBFM", "NBFM", Protocol.UNKNOWN),
|
||||
PASSPORT("Passport", "Passport", Protocol.PASSPORT),
|
||||
P25_PHASE1("P25 Phase 1", "P25-1", Protocol.APCO25),
|
||||
P25_PHASE2("P25 Phase 2", "P25-2", Protocol.APCO25),
|
||||
P25_PHASE2("P25 Phase 2", "P25-2", Protocol.APCO25_PHASE2),
|
||||
|
||||
//Auxiliary Decoders
|
||||
FLEETSYNC2("Fleetsync II", "Fleetsync2", Protocol.FLEETSYNC),
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.source.ISourceEventProvider;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
|
||||
/**
|
||||
* Decoder that provides feedback to signal source(s) via SourceEvent broadcasts and supports registering source
|
||||
* event listeners.
|
||||
*/
|
||||
public abstract class FeedbackDecoder extends Decoder implements ISourceEventProvider
|
||||
{
|
||||
private Listener<SourceEvent> mSourceEventListener;
|
||||
|
||||
/**
|
||||
* Registers the listener to receive source events from this decoder
|
||||
*/
|
||||
@Override
|
||||
public void setSourceEventListener(Listener<SourceEvent> listener)
|
||||
{
|
||||
mSourceEventListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deregisters the listener from receiving source events from this decoder.
|
||||
*/
|
||||
@Override
|
||||
public void removeSourceEventListener()
|
||||
{
|
||||
mSourceEventListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts the specified source event to the optional registered source event listener
|
||||
*/
|
||||
public void broadcast(SourceEvent sourceEvent)
|
||||
{
|
||||
if(mSourceEventListener != null)
|
||||
{
|
||||
mSourceEventListener.receive(sourceEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.filter.FilterSet;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.StuffBitsMessage;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
@@ -114,6 +115,12 @@ public class MessageActivityModel extends AbstractTableModel implements Listener
|
||||
|
||||
public void receive(final IMessage message)
|
||||
{
|
||||
//Don't process tail bits or stuff bits message fragments
|
||||
if(message instanceof StuffBitsMessage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(mMessageFilter.passes(message))
|
||||
{
|
||||
final MessageItem messageItem = new MessageItem(message);
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.fleetsync2.identifier;
|
||||
@@ -31,7 +33,7 @@ public class FleetsyncIdentifier extends TalkgroupIdentifier implements Comparab
|
||||
{
|
||||
public FleetsyncIdentifier(Integer talkgroup, Role role)
|
||||
{
|
||||
super(talkgroup, role, false);
|
||||
super(talkgroup, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.ltrnet.identifier;
|
||||
@@ -31,7 +33,7 @@ public class LtrNetRadioIdentifier extends TalkgroupIdentifier implements Compar
|
||||
{
|
||||
public LtrNetRadioIdentifier(int value, Role role)
|
||||
{
|
||||
super(value, role, false);
|
||||
super(value, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.mdc1200.identifier;
|
||||
@@ -35,7 +37,7 @@ public class MDC1200Identifier extends TalkgroupIdentifier
|
||||
*/
|
||||
public MDC1200Identifier(Integer value, Role role)
|
||||
{
|
||||
super(value, role, false);
|
||||
super(value, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.mpt1327.identifier;
|
||||
@@ -35,7 +37,7 @@ public class MPT1327Talkgroup extends TalkgroupIdentifier
|
||||
{
|
||||
public MPT1327Talkgroup(Integer value, Role role)
|
||||
{
|
||||
super(value, role, false);
|
||||
super(value, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -98,7 +98,9 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
private List<Channel> mManagedPhase2TrafficChannels;
|
||||
|
||||
private Map<APCO25Channel,Channel> mAllocatedTrafficChannelMap = new ConcurrentHashMap<>();
|
||||
private Map<APCO25Channel,P25ChannelGrantEvent> mChannelGrantEventMap = new ConcurrentHashMap<>();
|
||||
private Map<APCO25Channel,P25ChannelGrantEvent> mPhase1ChannelGrantEventMap = new ConcurrentHashMap<>();
|
||||
private Map<APCO25Channel,P25ChannelGrantEvent> mPhase2TS0ChannelGrantEventMap = new ConcurrentHashMap<>();
|
||||
private Map<APCO25Channel,P25ChannelGrantEvent> mPhase2TS1ChannelGrantEventMap = new ConcurrentHashMap<>();
|
||||
|
||||
private Listener<ChannelEvent> mChannelEventListener;
|
||||
private Listener<IDecodeEvent> mDecodeEventListener;
|
||||
@@ -271,7 +273,7 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
IdentifierCollection identifierCollection, Opcode opcode, long timestamp)
|
||||
{
|
||||
|
||||
P25ChannelGrantEvent event = mChannelGrantEventMap.get(apco25Channel);
|
||||
P25ChannelGrantEvent event = mPhase1ChannelGrantEventMap.get(apco25Channel);
|
||||
|
||||
if(event != null && isSameCall(identifierCollection, event.getIdentifierCollection()))
|
||||
{
|
||||
@@ -287,11 +289,11 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent continuationGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString() + " - Continue")
|
||||
.details("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("PHASE 1 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, continuationGrantEvent);
|
||||
mPhase1ChannelGrantEventMap.put(apco25Channel, continuationGrantEvent);
|
||||
broadcast(continuationGrantEvent);
|
||||
}
|
||||
}
|
||||
@@ -309,7 +311,7 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
if(trafficChannel != null)
|
||||
{
|
||||
event.setEventDescription(getEventType(opcode, serviceOptions).toString());
|
||||
event.setDetails("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"));
|
||||
event.setDetails("PHASE 1 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""));
|
||||
event.setChannelDescriptor(apco25Channel);
|
||||
broadcast(event);
|
||||
SourceConfigTuner sourceConfig = new SourceConfigTuner();
|
||||
@@ -328,11 +330,11 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent channelGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString() + " - Ignored")
|
||||
.details("DATA CALL IGNORED: " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("DATA CALL IGNORED: " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
mPhase1ChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
|
||||
broadcast(channelGrantEvent);
|
||||
return;
|
||||
@@ -341,11 +343,11 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent channelGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString())
|
||||
.details("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("PHASE 1 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
mPhase1ChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
|
||||
//Allocate a traffic channel for the downlink frequency if one isn't already allocated
|
||||
//NOTE: we could also allocate a traffic channel for the uplink frequency here, in the future
|
||||
@@ -388,9 +390,25 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
((MutableIdentifierCollection)identifierCollection).silentUpdate(ScrambleParameterIdentifier.create(mPhase2ScrambleParameters));
|
||||
}
|
||||
|
||||
P25ChannelGrantEvent event = mChannelGrantEventMap.get(apco25Channel);
|
||||
int timeslot = apco25Channel.getTimeslot();
|
||||
|
||||
identifierCollection.setTimeslot(apco25Channel.getTimeslot());
|
||||
P25ChannelGrantEvent event = null;
|
||||
|
||||
if(timeslot == 0)
|
||||
{
|
||||
event = mPhase2TS0ChannelGrantEventMap.get(apco25Channel);
|
||||
}
|
||||
else if(timeslot == 1)
|
||||
{
|
||||
event = mPhase2TS1ChannelGrantEventMap.get(apco25Channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error("Ignoring: Invalid timeslot [" + timeslot + "] detected for P25 Phase 2 Channel Grant.");
|
||||
return;
|
||||
}
|
||||
|
||||
identifierCollection.setTimeslot(timeslot);
|
||||
|
||||
if(event != null && isSameCall(identifierCollection, event.getIdentifierCollection()))
|
||||
{
|
||||
@@ -406,11 +424,19 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent continuationGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString() + " - Continue")
|
||||
.details("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("PHASE 2 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, continuationGrantEvent);
|
||||
if(timeslot == 0)
|
||||
{
|
||||
mPhase2TS0ChannelGrantEventMap.put(apco25Channel, continuationGrantEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
mPhase2TS1ChannelGrantEventMap.put(apco25Channel, continuationGrantEvent);
|
||||
}
|
||||
|
||||
broadcast(continuationGrantEvent);
|
||||
}
|
||||
}
|
||||
@@ -429,7 +455,7 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
if(trafficChannel != null)
|
||||
{
|
||||
event.setEventDescription(getEventType(opcode, serviceOptions).toString());
|
||||
event.setDetails("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"));
|
||||
event.setDetails("PHASE 2 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""));
|
||||
event.setChannelDescriptor(apco25Channel);
|
||||
broadcast(event);
|
||||
SourceConfigTuner sourceConfig = new SourceConfigTuner();
|
||||
@@ -456,11 +482,11 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent channelGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString() + " - Ignored")
|
||||
.details("DATA CALL IGNORED: " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("PHASE 2 DATA CALL IGNORED: " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
mPhase1ChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
|
||||
broadcast(channelGrantEvent);
|
||||
return;
|
||||
@@ -469,11 +495,18 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent channelGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString())
|
||||
.details("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("PHASE 2 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
if(timeslot == 0)
|
||||
{
|
||||
mPhase2TS0ChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
mPhase2TS1ChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
}
|
||||
|
||||
//Allocate a traffic channel for the downlink frequency if one isn't already allocated
|
||||
//NOTE: we could also allocate a traffic channel for the uplink frequency here, in the future
|
||||
@@ -735,6 +768,53 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
*/
|
||||
public class TrafficChannelTeardownMonitor implements Listener<ChannelEvent>
|
||||
{
|
||||
/**
|
||||
* Removes any call events that are associated with the specified channel.
|
||||
* @param channel that was removed
|
||||
*/
|
||||
private void cleanupCallEvents(Channel channel)
|
||||
{
|
||||
if(channel.getSourceConfiguration() instanceof SourceConfigTuner)
|
||||
{
|
||||
long frequency = ((SourceConfigTuner)channel.getSourceConfiguration()).getFrequency();
|
||||
|
||||
if(channel.getDecodeConfiguration().getDecoderType() == DecoderType.P25_PHASE1)
|
||||
{
|
||||
List<APCO25Channel> channels = new ArrayList<>(mPhase1ChannelGrantEventMap.keySet());
|
||||
|
||||
for(APCO25Channel p25Channel: channels)
|
||||
{
|
||||
if(p25Channel.getDownlinkFrequency() == frequency)
|
||||
{
|
||||
mPhase1ChannelGrantEventMap.remove(p25Channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List<APCO25Channel> channels = new ArrayList<>(mPhase2TS0ChannelGrantEventMap.keySet());
|
||||
|
||||
for(APCO25Channel p25Channel: channels)
|
||||
{
|
||||
if(p25Channel.getDownlinkFrequency() == frequency)
|
||||
{
|
||||
mPhase2TS0ChannelGrantEventMap.remove(p25Channel);
|
||||
}
|
||||
}
|
||||
|
||||
channels = new ArrayList<>(mPhase2TS1ChannelGrantEventMap.keySet());
|
||||
|
||||
for(APCO25Channel p25Channel: channels)
|
||||
{
|
||||
if(p25Channel.getDownlinkFrequency() == frequency)
|
||||
{
|
||||
mPhase2TS1ChannelGrantEventMap.remove(p25Channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void receive(ChannelEvent channelEvent)
|
||||
{
|
||||
@@ -773,15 +853,9 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
{
|
||||
mAvailablePhase2TrafficChannelQueue.add(channel);
|
||||
}
|
||||
|
||||
P25ChannelGrantEvent event = mChannelGrantEventMap.remove(toRemove);
|
||||
|
||||
if(event != null)
|
||||
{
|
||||
event.end(System.currentTimeMillis());
|
||||
broadcast(event);
|
||||
}
|
||||
}
|
||||
|
||||
cleanupCallEvents(channel);
|
||||
break;
|
||||
case NOTIFICATION_PROCESSING_START_REJECTED:
|
||||
APCO25Channel rejected = null;
|
||||
@@ -808,7 +882,7 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
mAvailablePhase2TrafficChannelQueue.add(channel);
|
||||
}
|
||||
|
||||
P25ChannelGrantEvent event = mChannelGrantEventMap.get(rejected);
|
||||
P25ChannelGrantEvent event = mPhase1ChannelGrantEventMap.get(rejected);
|
||||
|
||||
if(event != null)
|
||||
{
|
||||
@@ -826,6 +900,8 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
broadcast(event);
|
||||
}
|
||||
}
|
||||
|
||||
cleanupCallEvents(channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ public class P25P2AudioModule extends AmbeAudioModule implements IdentifierUpdat
|
||||
private static final String METADATA_TYPE_CALL_PROGRESS = "CALL PROGRESS";
|
||||
|
||||
private Listener<IdentifierUpdateNotification> mIdentifierUpdateNotificationListener;
|
||||
private SquelchStateListener mSquelchStateListener = new SquelchStateListener();
|
||||
private MetadataProcessor mDtmfMetadataProcessor;
|
||||
private MetadataProcessor mKnoxMetadataProcessor;
|
||||
private MetadataProcessor mToneMetadataProcessor;
|
||||
@@ -84,7 +85,7 @@ public class P25P2AudioModule extends AmbeAudioModule implements IdentifierUpdat
|
||||
@Override
|
||||
public Listener<SquelchStateEvent> getSquelchStateListener()
|
||||
{
|
||||
return null;
|
||||
return mSquelchStateListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -122,7 +122,10 @@ public class P25Channel implements IChannelDescriptor
|
||||
@Override
|
||||
public void setFrequencyBand(IFrequencyBand frequencyBand)
|
||||
{
|
||||
mFrequencyBand = frequencyBand;
|
||||
if(frequencyBand.getIdentifier() == getDownlinkBandIdentifier())
|
||||
{
|
||||
mFrequencyBand = frequencyBand;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -184,19 +187,36 @@ public class P25Channel implements IChannelDescriptor
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(getDownlinkBandIdentifier() == getUplinkBandIdentifier() && getDownlinkChannelNumber() == getUplinkChannelNumber())
|
||||
{
|
||||
return getDownlinkBandIdentifier() + "-" + (getDownlinkLogicalChannelNumber());
|
||||
sb.append(getDownlinkBandIdentifier()).append("-").append(getDownlinkLogicalChannelNumber());
|
||||
}
|
||||
else if(hasUplinkChannel())
|
||||
{
|
||||
return getDownlinkBandIdentifier() + "-" + (getDownlinkLogicalChannelNumber()) + "/" +
|
||||
getUplinkBandIdentifier() + "-" + (getUplinkLogicalChannelNumber());
|
||||
sb.append(getDownlinkBandIdentifier())
|
||||
.append("-")
|
||||
.append(getDownlinkLogicalChannelNumber())
|
||||
.append("/")
|
||||
.append(getUplinkBandIdentifier())
|
||||
.append("-")
|
||||
.append(getUplinkLogicalChannelNumber());
|
||||
}
|
||||
else
|
||||
{
|
||||
return getDownlinkBandIdentifier() + "-" + (getDownlinkLogicalChannelNumber()) + "/-----";
|
||||
sb.append(getDownlinkBandIdentifier())
|
||||
.append("-")
|
||||
.append(getDownlinkLogicalChannelNumber())
|
||||
.append("/-----");
|
||||
}
|
||||
|
||||
if(isTDMAChannel())
|
||||
{
|
||||
sb.append(" TS").append(getTimeslot());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.identifier.channel;
|
||||
@@ -36,11 +38,13 @@ public class P25ExplicitChannel extends P25Channel implements Comparable<P25Chan
|
||||
mUplinkChannelNumber = uplinkChannelNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUplinkBandIdentifier()
|
||||
{
|
||||
return mUplinkBandIdentifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUplinkChannelNumber()
|
||||
{
|
||||
return mUplinkChannelNumber;
|
||||
@@ -51,7 +55,8 @@ public class P25ExplicitChannel extends P25Channel implements Comparable<P25Chan
|
||||
{
|
||||
if(mUplinkFrequencyBand != null)
|
||||
{
|
||||
return mUplinkFrequencyBand.getUplinkFrequency(getUplinkChannelNumber());
|
||||
//Note: we explicitly use the downlink frequency from the uplink channel frequency band here
|
||||
return mUplinkFrequencyBand.getDownlinkFrequency(getUplinkChannelNumber());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.identifier.radio;
|
||||
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.radio.FullyQualifiedRadioIdentifier;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
* Fully Qualified Radio Identifier (talkgroup) that includes WACN, System, and Radio Address.
|
||||
*/
|
||||
public class APCO25FullyQualifiedRadioIdentifier extends FullyQualifiedRadioIdentifier
|
||||
{
|
||||
public APCO25FullyQualifiedRadioIdentifier(int wacn, int system, int id, Role role)
|
||||
{
|
||||
super(wacn, system, id, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Protocol getProtocol()
|
||||
{
|
||||
return Protocol.APCO25;
|
||||
}
|
||||
|
||||
public static APCO25FullyQualifiedRadioIdentifier createFrom(int wacn, int system, int id)
|
||||
{
|
||||
return new APCO25FullyQualifiedRadioIdentifier(wacn, system, id, Role.FROM);
|
||||
}
|
||||
|
||||
public static APCO25FullyQualifiedRadioIdentifier createTo(int wacn, int system, int id)
|
||||
{
|
||||
return new APCO25FullyQualifiedRadioIdentifier(wacn, system, id, Role.TO);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.identifier.radio;
|
||||
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.radio.RadioIdentifier;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
* APCO-25 Radio Identifier
|
||||
*/
|
||||
public class APCO25RadioIdentifier extends RadioIdentifier
|
||||
{
|
||||
public APCO25RadioIdentifier(Integer value, Role role)
|
||||
{
|
||||
super(value, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Protocol getProtocol()
|
||||
{
|
||||
return Protocol.APCO25;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an APCO-25 TO radio identifier
|
||||
*/
|
||||
public static RadioIdentifier createTo(int radioId)
|
||||
{
|
||||
return new APCO25RadioIdentifier(radioId, Role.TO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an APCO-25 FROM radio identifier
|
||||
*/
|
||||
public static RadioIdentifier createFrom(int radioId)
|
||||
{
|
||||
return new APCO25RadioIdentifier(radioId, Role.FROM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an APCO-25 ANY radio identifier
|
||||
*/
|
||||
public static RadioIdentifier createAny(int radioId)
|
||||
{
|
||||
return new APCO25RadioIdentifier(radioId, Role.ANY);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,28 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.module.decode.p25.identifier.talkgroup;
|
||||
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
|
||||
/**
|
||||
* APCO25 Announcement Talkgroup - grouping of talkgroups within a system.
|
||||
@@ -34,13 +36,13 @@ public class APCO25AnnouncementTalkgroup extends APCO25Talkgroup
|
||||
*/
|
||||
public APCO25AnnouncementTalkgroup(Integer value)
|
||||
{
|
||||
super(value, Role.BROADCAST, true);
|
||||
super(value, Role.BROADCAST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an APCO-25 announcement group talkgroup identifier
|
||||
*/
|
||||
public static Identifier create(int talkgroup)
|
||||
public static TalkgroupIdentifier create(int talkgroup)
|
||||
{
|
||||
return new APCO25AnnouncementTalkgroup(talkgroup);
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.module.decode.p25.identifier.talkgroup;
|
||||
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
|
||||
/**
|
||||
* APCO25 Talkgroup Identifier with an ANY role.
|
||||
*/
|
||||
public class APCO25AnyTalkgroup extends APCO25Talkgroup
|
||||
{
|
||||
/**
|
||||
* Constructs an APCO25 Talkgroup Identifier with an ANY role.
|
||||
*
|
||||
* @param value of the talkgroup
|
||||
*/
|
||||
public APCO25AnyTalkgroup(Integer value)
|
||||
{
|
||||
super(value, Role.ANY, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ANY APCO-25 talkgroup identifier
|
||||
*/
|
||||
public static TalkgroupIdentifier create(int talkgroup)
|
||||
{
|
||||
return new APCO25AnyTalkgroup(talkgroup);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.module.decode.p25.identifier.talkgroup;
|
||||
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
|
||||
/**
|
||||
* APCO25 Talkgroup Identifier with a FROM role.
|
||||
*/
|
||||
public class APCO25FromTalkgroup extends APCO25Talkgroup
|
||||
{
|
||||
public APCO25FromTalkgroup(Integer value, boolean isGroup)
|
||||
{
|
||||
super(value, Role.FROM, isGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an individual FROM APCO-25 talkgroup identifier
|
||||
*/
|
||||
public static TalkgroupIdentifier createIndividual(int talkgroup)
|
||||
{
|
||||
return new APCO25FromTalkgroup(talkgroup, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a FROM APCO-25 talkgroup identifier
|
||||
*/
|
||||
public static TalkgroupIdentifier createGroup(int talkgroup)
|
||||
{
|
||||
return new APCO25FromTalkgroup(talkgroup, true);
|
||||
}
|
||||
}
|
||||
@@ -22,21 +22,18 @@
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.identifier.talkgroup;
|
||||
|
||||
import io.github.dsheirer.identifier.Form;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.IdentifierClass;
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.talkgroup.FullyQualifiedIdentifier;
|
||||
import io.github.dsheirer.identifier.talkgroup.FullyQualifiedTalkgroupIdentifier;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
* Fully Qualified Radio Identifier (talkgroup) that includes WACN, System, and Radio Address.
|
||||
*/
|
||||
public class APCO25FullyQualifiedIdentifier extends Identifier<FullyQualifiedIdentifier>
|
||||
public class APCO25FullyQualifiedTalkgroupIdentifier extends FullyQualifiedTalkgroupIdentifier
|
||||
{
|
||||
public APCO25FullyQualifiedIdentifier(FullyQualifiedIdentifier value, Role role)
|
||||
public APCO25FullyQualifiedTalkgroupIdentifier(int wacn, int system, int id, Role role)
|
||||
{
|
||||
super(value, IdentifierClass.USER, Form.FULLY_QUALIFIED_IDENTIFIER, role);
|
||||
super(wacn, system, id, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,13 +42,18 @@ public class APCO25FullyQualifiedIdentifier extends Identifier<FullyQualifiedIde
|
||||
return Protocol.APCO25;
|
||||
}
|
||||
|
||||
public static APCO25FullyQualifiedIdentifier createFrom(int wacn, int system, int id)
|
||||
public static APCO25FullyQualifiedTalkgroupIdentifier createFrom(int wacn, int system, int id)
|
||||
{
|
||||
return new APCO25FullyQualifiedIdentifier(FullyQualifiedIdentifier.create(wacn, system, id), Role.FROM);
|
||||
return new APCO25FullyQualifiedTalkgroupIdentifier(wacn, system, id, Role.FROM);
|
||||
}
|
||||
|
||||
public static APCO25FullyQualifiedIdentifier createTo(int wacn, int system, int id)
|
||||
public static APCO25FullyQualifiedTalkgroupIdentifier createTo(int wacn, int system, int id)
|
||||
{
|
||||
return new APCO25FullyQualifiedIdentifier(FullyQualifiedIdentifier.create(wacn, system, id), Role.TO);
|
||||
return new APCO25FullyQualifiedTalkgroupIdentifier(wacn, system, id, Role.TO);
|
||||
}
|
||||
|
||||
public static APCO25FullyQualifiedTalkgroupIdentifier createAny(int wacn, int system, int id)
|
||||
{
|
||||
return new APCO25FullyQualifiedTalkgroupIdentifier(wacn, system, id, Role.ANY);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.module.decode.p25.identifier.talkgroup;
|
||||
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
|
||||
/**
|
||||
* APCO25 Talkgroup Identifier with a FROM role.
|
||||
*/
|
||||
public class APCO25IdentifierTalkgroup extends APCO25Talkgroup
|
||||
{
|
||||
public APCO25IdentifierTalkgroup(Integer value, boolean isGroup)
|
||||
{
|
||||
super(value, Role.IDENTIFIER, isGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an individual FROM APCO-25 talkgroup identifier
|
||||
*/
|
||||
public static TalkgroupIdentifier createIndividual(int talkgroup)
|
||||
{
|
||||
return new APCO25IdentifierTalkgroup(talkgroup, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a FROM APCO-25 talkgroup identifier
|
||||
*/
|
||||
public static TalkgroupIdentifier createGroup(int talkgroup)
|
||||
{
|
||||
return new APCO25IdentifierTalkgroup(talkgroup, true);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.identifier.talkgroup;
|
||||
@@ -26,9 +28,14 @@ import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
public class APCO25Talkgroup extends TalkgroupIdentifier
|
||||
{
|
||||
public APCO25Talkgroup(Integer value, Role role, boolean isGroup)
|
||||
public APCO25Talkgroup(Integer value)
|
||||
{
|
||||
super(value, role, isGroup);
|
||||
super(value, Role.TO);
|
||||
}
|
||||
|
||||
public APCO25Talkgroup(Integer value, Role role)
|
||||
{
|
||||
super(value, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,4 +43,20 @@ public class APCO25Talkgroup extends TalkgroupIdentifier
|
||||
{
|
||||
return Protocol.APCO25;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an APCO-25 TO talkgroup identifier
|
||||
*/
|
||||
public static TalkgroupIdentifier create(int talkgroup)
|
||||
{
|
||||
return new APCO25Talkgroup(talkgroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an APCO-25 talkgroup identifier with ANY role
|
||||
*/
|
||||
public static TalkgroupIdentifier createAny(int talkgroup)
|
||||
{
|
||||
return new APCO25Talkgroup(talkgroup, Role.ANY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.module.decode.p25.identifier.talkgroup;
|
||||
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
|
||||
/**
|
||||
* APCO25 Talkgroup Identifier with a FROM role.
|
||||
*/
|
||||
public class APCO25ToTalkgroup extends APCO25Talkgroup
|
||||
{
|
||||
public APCO25ToTalkgroup(Integer value, boolean isGroup)
|
||||
{
|
||||
super(value, Role.TO, isGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TO APCO-25 group talkgroup identifier
|
||||
*/
|
||||
public static TalkgroupIdentifier createGroup(int talkgroup)
|
||||
{
|
||||
return new APCO25ToTalkgroup(talkgroup, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TO APCO-25 individual talkgroup identifier
|
||||
*/
|
||||
public static TalkgroupIdentifier createIndividual(int talkgroup)
|
||||
{
|
||||
return new APCO25ToTalkgroup(talkgroup, false);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.module.decode.p25.phase1;
|
||||
|
||||
@@ -72,9 +74,9 @@ public class P25P1DataUnitDetector implements Listener<Dibit>, ISyncDetectListen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
dispatchSyncLoss(0);
|
||||
dispatchSyncLoss(bitsProcessed);
|
||||
}
|
||||
|
||||
private void dispatchSyncLoss(int bitsProcessed)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -23,8 +23,8 @@ package io.github.dsheirer.module.decode.p25.phase1;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.Dibit;
|
||||
import io.github.dsheirer.dsp.symbol.DibitToByteBufferAssembler;
|
||||
import io.github.dsheirer.module.decode.Decoder;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.FeedbackDecoder;
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.IReusableByteBufferProvider;
|
||||
@@ -32,10 +32,9 @@ import io.github.dsheirer.sample.buffer.IReusableComplexBufferListener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableByteBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.source.ISourceEventListener;
|
||||
import io.github.dsheirer.source.ISourceEventProvider;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
|
||||
public abstract class P25P1Decoder extends Decoder implements ISourceEventListener, ISourceEventProvider,
|
||||
public abstract class P25P1Decoder extends FeedbackDecoder implements ISourceEventListener,
|
||||
IReusableComplexBufferListener, Listener<ReusableComplexBuffer>, IReusableByteBufferProvider
|
||||
{
|
||||
private double mSampleRate;
|
||||
@@ -131,24 +130,6 @@ public abstract class P25P1Decoder extends Decoder implements ISourceEventListen
|
||||
mMessageProcessor = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source event listener to receive source events from this decoder.
|
||||
*/
|
||||
@Override
|
||||
public void setSourceEventListener(Listener<SourceEvent> listener)
|
||||
{
|
||||
mSourceEventListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a registered source event listener from receiving source events from this decoder
|
||||
*/
|
||||
@Override
|
||||
public void removeSourceEventListener()
|
||||
{
|
||||
mSourceEventListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<SourceEvent> getSourceEventListener()
|
||||
{
|
||||
@@ -168,19 +149,6 @@ public abstract class P25P1Decoder extends Decoder implements ISourceEventListen
|
||||
*/
|
||||
protected abstract void process(SourceEvent sourceEvent);
|
||||
|
||||
/**
|
||||
* Broadcasts the source event to an optional registered listener. This method should primarily be used to
|
||||
* issue frequency correction requests to the channel source.
|
||||
* @param sourceEvent to broadcast
|
||||
*/
|
||||
public void broadcast(SourceEvent sourceEvent)
|
||||
{
|
||||
if(mSourceEventListener != null)
|
||||
{
|
||||
mSourceEventListener.receive(sourceEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener interface to receive reusable complex buffers
|
||||
*/
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.module.decode.p25.phase1;
|
||||
|
||||
@@ -26,8 +28,9 @@ import io.github.dsheirer.dsp.filter.fir.complex.ComplexFIRFilter2;
|
||||
import io.github.dsheirer.dsp.gain.ComplexFeedForwardGainControl;
|
||||
import io.github.dsheirer.dsp.psk.DQPSKDecisionDirectedDemodulator;
|
||||
import io.github.dsheirer.dsp.psk.InterpolatingSampleBuffer;
|
||||
import io.github.dsheirer.dsp.psk.pll.AdaptivePLLGainMonitor;
|
||||
import io.github.dsheirer.dsp.psk.pll.CostasLoop;
|
||||
import io.github.dsheirer.dsp.psk.pll.FrequencyCorrectionSyncMonitor;
|
||||
import io.github.dsheirer.dsp.psk.pll.PLLBandwidth;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
@@ -45,7 +48,7 @@ public class P25P1DecoderC4FM extends P25P1Decoder
|
||||
protected InterpolatingSampleBuffer mInterpolatingSampleBuffer;
|
||||
protected DQPSKDecisionDirectedDemodulator mQPSKDemodulator;
|
||||
protected CostasLoop mCostasLoop;
|
||||
protected AdaptivePLLGainMonitor mPLLGainMonitor;
|
||||
protected FrequencyCorrectionSyncMonitor mFrequencyCorrectionSyncMonitor;
|
||||
protected P25P1MessageFramer mMessageFramer;
|
||||
private ComplexFeedForwardGainControl mAGC = new ComplexFeedForwardGainControl(32);
|
||||
private Map<Double,float[]> mBasebandFilters = new HashMap<>();
|
||||
@@ -68,7 +71,8 @@ public class P25P1DecoderC4FM extends P25P1Decoder
|
||||
mBasebandFilter = new ComplexFIRFilter2(getBasebandFilter());
|
||||
|
||||
mCostasLoop = new CostasLoop(getSampleRate(), getSymbolRate());
|
||||
mPLLGainMonitor = new AdaptivePLLGainMonitor(mCostasLoop, this);
|
||||
mCostasLoop.setPLLBandwidth(PLLBandwidth.BW_300);
|
||||
mFrequencyCorrectionSyncMonitor = new FrequencyCorrectionSyncMonitor(mCostasLoop, this);
|
||||
mInterpolatingSampleBuffer = new InterpolatingSampleBuffer(getSamplesPerSymbol(), SAMPLE_COUNTER_GAIN);
|
||||
|
||||
mQPSKDemodulator = new DQPSKDecisionDirectedDemodulator(mCostasLoop, mInterpolatingSampleBuffer);
|
||||
@@ -81,7 +85,7 @@ public class P25P1DecoderC4FM extends P25P1Decoder
|
||||
//The Costas Loop receives symbol-inversion correction requests when detected.
|
||||
//The PLL gain monitor receives sync detect/loss signals from the message framer
|
||||
mMessageFramer = new P25P1MessageFramer(mCostasLoop, DecoderType.P25_PHASE1.getProtocol().getBitRate());
|
||||
mMessageFramer.setSyncDetectListener(mPLLGainMonitor);
|
||||
mMessageFramer.setSyncDetectListener(mFrequencyCorrectionSyncMonitor);
|
||||
mMessageFramer.setListener(getMessageProcessor());
|
||||
mMessageFramer.setSampleRate(sampleRate);
|
||||
|
||||
@@ -202,6 +206,6 @@ public class P25P1DecoderC4FM extends P25P1Decoder
|
||||
public void reset()
|
||||
{
|
||||
mCostasLoop.reset();
|
||||
mPLLGainMonitor.reset();
|
||||
mFrequencyCorrectionSyncMonitor.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -27,8 +27,9 @@ import io.github.dsheirer.dsp.filter.fir.complex.ComplexFIRFilter2;
|
||||
import io.github.dsheirer.dsp.gain.ComplexFeedForwardGainControl;
|
||||
import io.github.dsheirer.dsp.psk.DQPSKGardnerDemodulator;
|
||||
import io.github.dsheirer.dsp.psk.InterpolatingSampleBuffer;
|
||||
import io.github.dsheirer.dsp.psk.pll.AdaptivePLLGainMonitor;
|
||||
import io.github.dsheirer.dsp.psk.pll.CostasLoop;
|
||||
import io.github.dsheirer.dsp.psk.pll.FrequencyCorrectionSyncMonitor;
|
||||
import io.github.dsheirer.dsp.psk.pll.PLLBandwidth;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import io.github.dsheirer.record.binary.BinaryRecorder;
|
||||
@@ -56,8 +57,8 @@ public class P25P1DecoderLSM extends P25P1Decoder
|
||||
protected DQPSKGardnerDemodulator mQPSKDemodulator;
|
||||
protected P25P1MessageFramer mMessageFramer;
|
||||
protected CostasLoop mCostasLoop;
|
||||
protected AdaptivePLLGainMonitor mPLLGainMonitor;
|
||||
protected InterpolatingSampleBuffer mInterpolatingSampleBuffer;
|
||||
protected FrequencyCorrectionSyncMonitor mFrequencyCorrectionSyncMonitor;
|
||||
|
||||
/**
|
||||
* P25 Phase 1 - linear simulcast modulation (LSM) decoder. Uses Differential QPSK decoding with a Costas PLL and
|
||||
@@ -81,7 +82,8 @@ public class P25P1DecoderLSM extends P25P1Decoder
|
||||
mBasebandFilter = new ComplexFIRFilter2(getBasebandFilter());
|
||||
|
||||
mCostasLoop = new CostasLoop(getSampleRate(), getSymbolRate());
|
||||
mPLLGainMonitor = new AdaptivePLLGainMonitor(mCostasLoop, this);
|
||||
mCostasLoop.setPLLBandwidth(PLLBandwidth.BW_200);
|
||||
mFrequencyCorrectionSyncMonitor = new FrequencyCorrectionSyncMonitor(mCostasLoop, this);
|
||||
|
||||
mInterpolatingSampleBuffer = new InterpolatingSampleBuffer(getSamplesPerSymbol(), SAMPLE_COUNTER_GAIN);
|
||||
|
||||
@@ -95,7 +97,7 @@ public class P25P1DecoderLSM extends P25P1Decoder
|
||||
}
|
||||
|
||||
mMessageFramer = new P25P1MessageFramer(mCostasLoop, DecoderType.P25_PHASE1.getProtocol().getBitRate());
|
||||
mMessageFramer.setSyncDetectListener(mPLLGainMonitor);
|
||||
mMessageFramer.setSyncDetectListener(mFrequencyCorrectionSyncMonitor);
|
||||
mMessageFramer.setListener(getMessageProcessor());
|
||||
mMessageFramer.setSampleRate(sampleRate);
|
||||
mQPSKDemodulator.setSymbolListener(getDibitBroadcaster());
|
||||
@@ -163,7 +165,7 @@ public class P25P1DecoderLSM extends P25P1Decoder
|
||||
public void reset()
|
||||
{
|
||||
mCostasLoop.reset();
|
||||
mPLLGainMonitor.reset();
|
||||
mFrequencyCorrectionSyncMonitor.reset();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -1357,7 +1357,7 @@ public class P25P1DecoderState extends DecoderState implements IChannelEventList
|
||||
//Network Configuration Messages
|
||||
case MOTOROLA_OSP_TRAFFIC_CHANNEL_ID:
|
||||
case MOTOROLA_OSP_SYSTEM_LOADING:
|
||||
case MOTOROLA_OSP_CONTROL_CHANNEL_ID:
|
||||
case MOTOROLA_OSP_BASE_STATION_ID:
|
||||
case MOTOROLA_OSP_CONTROL_CHANNEL_PLANNED_SHUTDOWN:
|
||||
case OSP_IDENTIFIER_UPDATE_TDMA:
|
||||
case OSP_IDENTIFIER_UPDATE_VHF_UHF_BANDS:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -28,16 +28,18 @@ import io.github.dsheirer.dsp.symbol.Dibit;
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.StuffBitsMessage;
|
||||
import io.github.dsheirer.message.SyncLossMessage;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.p25.audio.P25P1CallSequenceRecorder;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25Message;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.P25MessageFactory;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.pdu.PDUMessageFactory;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.pdu.PDUSequence;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.TSBKMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.TSBKMessageFactory;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.P25P2MessageFramer;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.P25P2MessageProcessor;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.enumeration.ScrambleParameters;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import io.github.dsheirer.record.binary.BinaryReader;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
@@ -45,8 +47,12 @@ import io.github.dsheirer.sample.buffer.ReusableByteBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* P25 Sync Detector and Message Framer. Includes capability to detect PLL out-of-phase lock errors
|
||||
@@ -59,7 +65,6 @@ public class P25P1MessageFramer implements Listener<Dibit>, IP25P1DataUnitDetect
|
||||
private P25P1DataUnitDetector mDataUnitDetector;
|
||||
private P25P1ChannelStatusProcessor mChannelStatusProcessor = new P25P1ChannelStatusProcessor();
|
||||
private Listener<Message> mMessageListener;
|
||||
|
||||
private boolean mAssemblingMessage = false;
|
||||
private CorrectedBinaryMessage mBinaryMessage;
|
||||
private P25P1DataUnitID mDataUnitID;
|
||||
@@ -411,7 +416,7 @@ public class P25P1MessageFramer implements Listener<Dibit>, IP25P1DataUnitDetect
|
||||
|
||||
if(mSyncDetectListener != null)
|
||||
{
|
||||
mSyncDetectListener.syncLost();
|
||||
mSyncDetectListener.syncLost(bitsProcessed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,58 +427,101 @@ public class P25P1MessageFramer implements Listener<Dibit>, IP25P1DataUnitDetect
|
||||
|
||||
if(bitsProcessed > 0 && mMessageListener != null)
|
||||
{
|
||||
mMessageListener.receive(new SyncLossMessage(getTimestamp(), bitsProcessed, Protocol.APCO25));
|
||||
if(bitsProcessed < 64)
|
||||
{
|
||||
mMessageListener.receive(new StuffBitsMessage(getTimestamp(), bitsProcessed, Protocol.APCO25));
|
||||
}
|
||||
else
|
||||
{
|
||||
mMessageListener.receive(new SyncLossMessage(getTimestamp(), bitsProcessed, Protocol.APCO25));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
P25P1DecoderLSM decoderLSM = new P25P1DecoderLSM();
|
||||
Path directory = Paths.get("/media/denny/500G1EXT4/RadioRecordings/Harris APCO25 Phase II");
|
||||
// Path directory = Paths.get("/media/denny/500G1EXT4/PBITRecordings");
|
||||
|
||||
final boolean phase1 = false;
|
||||
|
||||
// Path path = Paths.get("/media/denny/500G1EXT4/RadioRecordings/APCO25P2/DFW Airport Encrypted/20190719_073751_9600BPS_APCO25PHASE1_DFWAirport_Site_857_3875_baseband_20181213_223236.bits");
|
||||
Path path = Paths.get("/media/denny/500G1EXT4/RadioRecordings/20190720_071117_9600BPS_APCO25PHASE1_P25P2_HCPM_Metrocrest_Dallas_857_7625_phase_2_not_motorola_baseband_20181213_224616_control_channel.bits");
|
||||
|
||||
P25P1MessageFramer messageFramer = new P25P1MessageFramer(null, DecoderType.P25_PHASE1.getProtocol().getBitRate());
|
||||
|
||||
try(BinaryReader reader = new BinaryReader(path, 200))
|
||||
try
|
||||
{
|
||||
while(reader.hasNext())
|
||||
{
|
||||
messageFramer.receive(reader.next());
|
||||
}
|
||||
DirectoryStream<Path> stream = Files.newDirectoryStream(directory, "*Hills*TRAFFIC.bits");
|
||||
|
||||
stream.forEach(new Consumer<Path>()
|
||||
{
|
||||
@Override
|
||||
public void accept(Path path)
|
||||
{
|
||||
mLog.debug("Processing:" + path.toString());
|
||||
|
||||
if(phase1)
|
||||
{
|
||||
P25P1MessageFramer messageFramer = new P25P1MessageFramer(null, DecoderType.P25_PHASE1.getProtocol().getBitRate());
|
||||
P25P1MessageProcessor messageProcessor = new P25P1MessageProcessor();
|
||||
messageFramer.setListener(messageProcessor);
|
||||
messageProcessor.setMessageListener(new Listener<IMessage>()
|
||||
{
|
||||
@Override
|
||||
public void receive(IMessage message)
|
||||
{
|
||||
if(!(message instanceof StuffBitsMessage))
|
||||
{
|
||||
mLog.debug(message.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try(BinaryReader reader = new BinaryReader(path, 200))
|
||||
{
|
||||
while(reader.hasNext())
|
||||
{
|
||||
ReusableByteBuffer buffer = reader.next();
|
||||
messageFramer.receive(buffer);
|
||||
}
|
||||
}
|
||||
catch(Exception ioe)
|
||||
{
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
P25P2MessageFramer messageFramer = new P25P2MessageFramer(null, DecoderType.P25_PHASE2.getProtocol().getBitRate());
|
||||
ScrambleParameters scrambleParameters = new ScrambleParameters(123654, 813, 10); //Hills County
|
||||
messageFramer.setScrambleParameters(scrambleParameters);
|
||||
P25P2MessageProcessor messageProcessor = new P25P2MessageProcessor();
|
||||
messageFramer.setListener(messageProcessor);
|
||||
messageProcessor.setMessageListener(new Listener<IMessage>()
|
||||
{
|
||||
@Override
|
||||
public void receive(IMessage message)
|
||||
{
|
||||
mLog.debug(message.toString());
|
||||
}
|
||||
});
|
||||
|
||||
try(BinaryReader reader = new BinaryReader(path, 200))
|
||||
{
|
||||
while(reader.hasNext())
|
||||
{
|
||||
ReusableByteBuffer buffer = reader.next();
|
||||
messageFramer.receive(buffer);
|
||||
}
|
||||
}
|
||||
catch(Exception ioe)
|
||||
{
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
catch(Exception ioe)
|
||||
catch(IOException ioe)
|
||||
{
|
||||
ioe.printStackTrace();
|
||||
mLog.error("Error", ioe);
|
||||
}
|
||||
|
||||
P25P1MessageProcessor messageProcessor = new P25P1MessageProcessor();
|
||||
P25P1CallSequenceRecorder frameRecorder = new P25P1CallSequenceRecorder(new UserPreferences(), 154250000, "", "");
|
||||
messageFramer.setListener(messageProcessor);
|
||||
messageProcessor.setMessageListener(new Listener<IMessage>()
|
||||
{
|
||||
@Override
|
||||
public void receive(IMessage message)
|
||||
{
|
||||
frameRecorder.receive(message);
|
||||
mLog.debug(message.toString());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
try(BinaryReader reader = new BinaryReader(path, 200))
|
||||
{
|
||||
while(reader.hasNext())
|
||||
{
|
||||
messageFramer.receive(reader.next());
|
||||
}
|
||||
}
|
||||
catch(Exception ioe)
|
||||
{
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
|
||||
frameRecorder.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -23,6 +23,7 @@
|
||||
package io.github.dsheirer.module.decode.p25.phase1;
|
||||
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBand;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCAdjacentSiteStatusBroadcast;
|
||||
@@ -39,6 +40,7 @@ import io.github.dsheirer.module.decode.p25.phase1.message.pdu.ambtc.osp.AMBTCAd
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.pdu.ambtc.osp.AMBTCNetworkStatusBroadcast;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.pdu.ambtc.osp.AMBTCRFSSStatusBroadcast;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.TSBKMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.motorola.osp.MotorolaBaseStationId;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.standard.osp.AdjacentStatusBroadcast;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.standard.osp.NetworkStatusBroadcast;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.standard.osp.RFSSStatusBroadcast;
|
||||
@@ -95,6 +97,8 @@ public class P25P1NetworkConfigurationMonitor
|
||||
private Map<Integer,LCAdjacentSiteStatusBroadcastExplicit> mLCNeighborSitesExplicit = new HashMap<>();
|
||||
private Map<Integer,AdjacentStatusBroadcast> mTSBKNeighborSites = new HashMap<>();
|
||||
|
||||
private MotorolaBaseStationId mMotorolaBaseStationId;
|
||||
|
||||
private P25P1Decoder.Modulation mModulation;
|
||||
|
||||
/**
|
||||
@@ -173,6 +177,12 @@ public class P25P1NetworkConfigurationMonitor
|
||||
mSNDCPDataChannel = (SNDCPDataChannelAnnouncementExplicit)tsbk;
|
||||
}
|
||||
break;
|
||||
case MOTOROLA_OSP_BASE_STATION_ID:
|
||||
if(tsbk instanceof MotorolaBaseStationId)
|
||||
{
|
||||
mMotorolaBaseStationId = (MotorolaBaseStationId)tsbk;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,6 +324,31 @@ public class P25P1NetworkConfigurationMonitor
|
||||
mTSBKNeighborSites.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the identifier with an appended hexadecimal value when the identifier is an integer
|
||||
* @param identifier to format
|
||||
* @param width of the hex value with zero pre-padding
|
||||
* @return formatted identifier
|
||||
*/
|
||||
private String format(Identifier identifier, int width)
|
||||
{
|
||||
if(identifier.getValue() instanceof Integer)
|
||||
{
|
||||
String hex = Integer.toHexString((Integer)identifier.getValue());
|
||||
|
||||
while(hex.length() < width)
|
||||
{
|
||||
hex = "0" + hex;
|
||||
}
|
||||
|
||||
return hex.toUpperCase() + "[" + identifier.getValue() + "]";
|
||||
}
|
||||
else
|
||||
{
|
||||
return identifier.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public String getActivitySummary()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -323,26 +358,26 @@ public class P25P1NetworkConfigurationMonitor
|
||||
sb.append("\n\nNetwork\n");
|
||||
if(mTSBKNetworkStatusBroadcast != null)
|
||||
{
|
||||
sb.append(" NAC:").append(mTSBKNetworkStatusBroadcast.getNAC());
|
||||
sb.append(" WACN:").append(mTSBKNetworkStatusBroadcast.getWacn());
|
||||
sb.append(" SYSTEM:").append(mTSBKNetworkStatusBroadcast.getSystem());
|
||||
sb.append(" LRA:").append(mTSBKNetworkStatusBroadcast.getLocationRegistrationArea());
|
||||
sb.append(" WACN:").append(format(mTSBKNetworkStatusBroadcast.getWacn(), 5));
|
||||
sb.append(" SYSTEM:").append(format(mTSBKNetworkStatusBroadcast.getSystem(), 3));
|
||||
sb.append(" NAC:").append(format(mTSBKNetworkStatusBroadcast.getNAC(), 3));
|
||||
sb.append(" LRA:").append(format(mTSBKNetworkStatusBroadcast.getLocationRegistrationArea(), 2));
|
||||
}
|
||||
else if(mAMBTCNetworkStatusBroadcast != null)
|
||||
{
|
||||
sb.append(" NAC:").append(mAMBTCNetworkStatusBroadcast.getNAC());
|
||||
sb.append(" WACN:").append(mAMBTCNetworkStatusBroadcast.getWacn());
|
||||
sb.append(" SYSTEM:").append(mAMBTCNetworkStatusBroadcast.getSystem());
|
||||
sb.append(" WACN:").append(format(mAMBTCNetworkStatusBroadcast.getWacn(), 5));
|
||||
sb.append(" SYSTEM:").append(format(mAMBTCNetworkStatusBroadcast.getSystem(), 3));
|
||||
sb.append(" NAC:").append(format(mAMBTCNetworkStatusBroadcast.getNAC(), 3));
|
||||
}
|
||||
else if(mLCNetworkStatusBroadcast != null)
|
||||
{
|
||||
sb.append(" WACN:").append(mLCNetworkStatusBroadcast.getWACN());
|
||||
sb.append(" SYSTEM:").append(mLCNetworkStatusBroadcast.getSystem());
|
||||
sb.append(" WACN:").append(format(mLCNetworkStatusBroadcast.getWACN(), 5));
|
||||
sb.append(" SYSTEM:").append(format(mLCNetworkStatusBroadcast.getSystem(), 3));
|
||||
}
|
||||
else if(mLCNetworkStatusBroadcastExplicit != null)
|
||||
{
|
||||
sb.append(" WACN:").append(mLCNetworkStatusBroadcastExplicit.getWACN());
|
||||
sb.append(" SYSTEM:").append(mLCNetworkStatusBroadcastExplicit.getSystem());
|
||||
sb.append(" WACN:").append(format(mLCNetworkStatusBroadcastExplicit.getWACN(), 5));
|
||||
sb.append(" SYSTEM:").append(format(mLCNetworkStatusBroadcastExplicit.getSystem(), 3));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -350,12 +385,14 @@ public class P25P1NetworkConfigurationMonitor
|
||||
}
|
||||
|
||||
sb.append("\n\nCurrent Site\n");
|
||||
|
||||
if(mTSBKRFSSStatusBroadcast != null)
|
||||
{
|
||||
sb.append(" SYSTEM:").append(mTSBKRFSSStatusBroadcast.getSystem());
|
||||
sb.append(" SITE:").append(mTSBKRFSSStatusBroadcast.getSite());
|
||||
sb.append(" RF SUBSYSTEM:").append(mTSBKRFSSStatusBroadcast.getRfss());
|
||||
sb.append(" LOCATION REGISTRATION AREA:").append(mTSBKRFSSStatusBroadcast.getLocationRegistrationArea());
|
||||
sb.append(" SYSTEM:").append(format(mTSBKRFSSStatusBroadcast.getSystem(), 3));
|
||||
sb.append(" NAC:").append(format(mTSBKRFSSStatusBroadcast.getNAC(), 3));
|
||||
sb.append(" RFSS:").append(format(mTSBKRFSSStatusBroadcast.getRfss(), 2));
|
||||
sb.append(" SITE:").append(format(mTSBKRFSSStatusBroadcast.getSite(), 2));
|
||||
sb.append(" LRA:").append(format(mTSBKRFSSStatusBroadcast.getLocationRegistrationArea(), 2));
|
||||
sb.append(" STATUS:").append(mTSBKRFSSStatusBroadcast.isActiveNetworkConnectionToRfssControllerSite() ?
|
||||
"ACTIVE RFSS NETWORK CONNECTION\n" : "\n");
|
||||
sb.append(" PRI CONTROL CHANNEL:").append(mTSBKRFSSStatusBroadcast.getChannel());
|
||||
@@ -364,29 +401,30 @@ public class P25P1NetworkConfigurationMonitor
|
||||
}
|
||||
else if(mLCRFSSStatusBroadcast != null)
|
||||
{
|
||||
sb.append(" SYSTEM:").append(mLCRFSSStatusBroadcast.getSystem());
|
||||
sb.append(" SITE:").append(mLCRFSSStatusBroadcast.getSite());
|
||||
sb.append(" RF SUBSYSTEM:").append(mLCRFSSStatusBroadcast.getRfss());
|
||||
sb.append(" LOCATION REGISTRATION AREA:").append(mLCRFSSStatusBroadcast.getLocationRegistrationArea()).append("\n");
|
||||
sb.append(" SYSTEM:").append(format(mLCRFSSStatusBroadcast.getSystem(), 3));
|
||||
sb.append(" RFSS:").append(format(mLCRFSSStatusBroadcast.getRfss(), 2));
|
||||
sb.append(" SITE:").append(format(mLCRFSSStatusBroadcast.getSite(), 2));
|
||||
sb.append(" LRA:").append(format(mLCRFSSStatusBroadcast.getLocationRegistrationArea(), 2)).append("\n");
|
||||
sb.append(" PRI CONTROL CHANNEL:").append(mLCRFSSStatusBroadcast.getChannel());
|
||||
sb.append(" DOWNLINK:").append(mLCRFSSStatusBroadcast.getChannel().getDownlinkFrequency());
|
||||
sb.append(" UPLINK:").append(mLCRFSSStatusBroadcast.getChannel().getUplinkFrequency()).append("\n");
|
||||
}
|
||||
else if(mLCRFSSStatusBroadcastExplicit != null)
|
||||
{
|
||||
sb.append(" SITE:").append(mLCRFSSStatusBroadcastExplicit.getSite());
|
||||
sb.append(" RF SUBSYSTEM:").append(mLCRFSSStatusBroadcastExplicit.getRfss());
|
||||
sb.append(" LOCATION REGISTRATION AREA:").append(mLCRFSSStatusBroadcastExplicit.getLocationRegistrationArea()).append("\n");
|
||||
sb.append(" RFSS:").append(mLCRFSSStatusBroadcastExplicit.getRfss());
|
||||
sb.append(" SITE:").append(format(mLCRFSSStatusBroadcastExplicit.getSite(), 2));
|
||||
sb.append(" LRA:").append(format(mLCRFSSStatusBroadcastExplicit.getLocationRegistrationArea(), 2)).append("\n");
|
||||
sb.append(" PRI CONTROL CHANNEL:").append(mLCRFSSStatusBroadcastExplicit.getChannel());
|
||||
sb.append(" DOWNLINK:").append(mLCRFSSStatusBroadcastExplicit.getChannel().getDownlinkFrequency());
|
||||
sb.append(" UPLINK:").append(mLCRFSSStatusBroadcastExplicit.getChannel().getUplinkFrequency()).append("\n");
|
||||
}
|
||||
else if(mAMBTCRFSSStatusBroadcast != null)
|
||||
{
|
||||
sb.append(" SYSTEM:").append(mAMBTCRFSSStatusBroadcast.getSystem());
|
||||
sb.append(" SITE:").append(mAMBTCRFSSStatusBroadcast.getSite());
|
||||
sb.append(" RF SUBSYSTEM:").append(mAMBTCRFSSStatusBroadcast.getRFSS());
|
||||
sb.append(" LOCATION REGISTRATION AREA:").append(mAMBTCRFSSStatusBroadcast.getLRA());
|
||||
sb.append(" SYSTEM:").append(format(mAMBTCRFSSStatusBroadcast.getSystem(), 3));
|
||||
sb.append(" NAC:").append(format(mAMBTCRFSSStatusBroadcast.getNAC(), 3));
|
||||
sb.append(" RFSS:").append(format(mAMBTCRFSSStatusBroadcast.getRFSS(), 2));
|
||||
sb.append(" SITE:").append(format(mAMBTCRFSSStatusBroadcast.getSite(), 2));
|
||||
sb.append(" LRA:").append(format(mAMBTCRFSSStatusBroadcast.getLRA(), 2));
|
||||
sb.append(" STATUS:").append(mAMBTCRFSSStatusBroadcast.isActiveNetworkConnectionToRfssControllerSite() ?
|
||||
"ACTIVE RFSS NETWORK CONNECTION\n" : "\n");
|
||||
sb.append(" PRI CONTROL CHANNEL:").append(mAMBTCRFSSStatusBroadcast.getChannel());
|
||||
@@ -423,6 +461,11 @@ public class P25P1NetworkConfigurationMonitor
|
||||
sb.append(" UPLINK:").append(mSNDCPDataChannel.getChannel().getUplinkFrequency()).append("\n");
|
||||
}
|
||||
|
||||
if(mMotorolaBaseStationId != null)
|
||||
{
|
||||
sb.append(" STATION ID/LICENSE: " + mMotorolaBaseStationId.getCWID()).append("\n");
|
||||
}
|
||||
|
||||
if(mTSBKSystemServiceBroadcast != null)
|
||||
{
|
||||
sb.append(" AVAILABLE SERVICES:").append(mTSBKSystemServiceBroadcast.getAvailableServices());
|
||||
@@ -434,7 +477,6 @@ public class P25P1NetworkConfigurationMonitor
|
||||
sb.append(" SUPPORTED SERVICES:").append(mLCSystemServiceBroadcast.getSupportedServices());
|
||||
}
|
||||
|
||||
|
||||
sb.append("\nNeighbor Sites\n");
|
||||
Set<Integer> sites = new TreeSet<>();
|
||||
sites.addAll(mAMBTCNeighborSites.keySet());
|
||||
@@ -456,10 +498,11 @@ public class P25P1NetworkConfigurationMonitor
|
||||
if(mAMBTCNeighborSites.containsKey(site))
|
||||
{
|
||||
AMBTCAdjacentStatusBroadcast ambtc = mAMBTCNeighborSites.get(site);
|
||||
sb.append(" SYSTEM:").append(ambtc.getSystem());
|
||||
sb.append(" SITE:").append(ambtc.getSite());
|
||||
sb.append(" LRA:").append(ambtc.getLocationRegistrationArea());
|
||||
sb.append(" RFSS:").append(ambtc.getRfss());
|
||||
sb.append(" SYSTEM:").append(format(ambtc.getSystem(), 3));
|
||||
sb.append(" NAC:").append(format(ambtc.getNAC(), 3));
|
||||
sb.append(" RFSS:").append(format(ambtc.getRfss(), 2));
|
||||
sb.append(" SITE:").append(format(ambtc.getSite(), 2));
|
||||
sb.append(" LRA:").append(format(ambtc.getLocationRegistrationArea(), 2));
|
||||
sb.append(" CHANNEL:").append(ambtc.getChannel());
|
||||
sb.append(" DOWNLINK:").append(ambtc.getChannel().getDownlinkFrequency());
|
||||
sb.append(" UPLINK:").append(ambtc.getChannel().getUplinkFrequency()).append("\n");
|
||||
@@ -467,10 +510,10 @@ public class P25P1NetworkConfigurationMonitor
|
||||
if(mLCNeighborSites.containsKey(site))
|
||||
{
|
||||
LCAdjacentSiteStatusBroadcast lc = mLCNeighborSites.get(site);
|
||||
sb.append(" SYSTEM:").append(lc.getSystem());
|
||||
sb.append(" SITE:").append(lc.getSite());
|
||||
sb.append(" LRA:").append(lc.getLocationRegistrationArea());
|
||||
sb.append(" RFSS:").append(lc.getRfss());
|
||||
sb.append(" SYSTEM:").append(format(lc.getSystem(), 3));
|
||||
sb.append(" RFSS:").append(format(lc.getRfss(), 2));
|
||||
sb.append(" SITE:").append(format(lc.getSite(), 2));
|
||||
sb.append(" LRA:").append(format(lc.getLocationRegistrationArea(), 2));
|
||||
sb.append(" CHANNEL:").append(lc.getChannel());
|
||||
sb.append(" DOWNLINK:").append(lc.getChannel().getDownlinkFrequency());
|
||||
sb.append(" UPLINK:").append(lc.getChannel().getUplinkFrequency()).append("\n");
|
||||
@@ -480,9 +523,9 @@ public class P25P1NetworkConfigurationMonitor
|
||||
{
|
||||
LCAdjacentSiteStatusBroadcastExplicit lce = mLCNeighborSitesExplicit.get(site);
|
||||
sb.append(" SYSTEM:---");
|
||||
sb.append(" SITE:").append(lce.getSite());
|
||||
sb.append(" LRA:").append(lce.getLocationRegistrationArea());
|
||||
sb.append(" RFSS:").append(lce.getRfss());
|
||||
sb.append(" RFSS:").append(format(lce.getRfss(), 2));
|
||||
sb.append(" SITE:").append(format(lce.getSite(), 2));
|
||||
sb.append(" LRA:").append(format(lce.getLocationRegistrationArea(), 2));
|
||||
sb.append(" CHANNEL:").append(lce.getChannel());
|
||||
sb.append(" DOWNLINK:").append(lce.getChannel().getDownlinkFrequency());
|
||||
sb.append(" UPLINK:").append(lce.getChannel().getUplinkFrequency()).append("\n");
|
||||
@@ -490,10 +533,11 @@ public class P25P1NetworkConfigurationMonitor
|
||||
if(mTSBKNeighborSites.containsKey(site))
|
||||
{
|
||||
AdjacentStatusBroadcast asb = mTSBKNeighborSites.get(site);
|
||||
sb.append(" SYSTEM:").append(asb.getSystem());
|
||||
sb.append(" SITE:").append(asb.getSite());
|
||||
sb.append(" LRA:").append(asb.getLocationRegistrationArea());
|
||||
sb.append(" RFSS:").append(asb.getRfss());
|
||||
sb.append(" SYSTEM:").append(format(asb.getSystem(), 3));
|
||||
sb.append(" NAC:").append(format(asb.getNAC(), 3));
|
||||
sb.append(" RFSS:").append(format(asb.getRfss(), 2));
|
||||
sb.append(" SITE:").append(format(asb.getSite(), 2));
|
||||
sb.append(" LRA:").append(format(asb.getLocationRegistrationArea(), 2));
|
||||
sb.append(" CHANNEL:").append(asb.getChannel());
|
||||
sb.append(" DOWNLINK:").append(asb.getChannel().getDownlinkFrequency());
|
||||
sb.append(" UPLINK:").append(asb.getChannel().getUplinkFrequency());
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.module.decode.p25.phase1;
|
||||
|
||||
@@ -37,9 +39,10 @@ public class P25P1SyncDetector implements Listener<Dibit>
|
||||
* 90 degrees requires a correction of 1/4 of the symbol rate (1200Hz). An
|
||||
* error of 180 degrees requires a correction of 1/2 of the symbol rate */
|
||||
public static final double DEFAULT_SAMPLE_RATE = 50000.0;
|
||||
public static final double DEFAULT_SYMBOL_RATE = 4800;
|
||||
|
||||
public static final double FREQUENCY_PHASE_CORRECTION_90_DEGREES = 1200.0;
|
||||
public static final double FREQUENCY_PHASE_CORRECTION_180_DEGREES = 2400.0;
|
||||
public static final double FREQUENCY_PHASE_CORRECTION_90_DEGREES = DEFAULT_SYMBOL_RATE / 4.0;
|
||||
public static final double FREQUENCY_PHASE_CORRECTION_180_DEGREES = DEFAULT_SYMBOL_RATE / 2.0;
|
||||
|
||||
private MultiSyncPatternMatcher mMatcher;
|
||||
private SoftSyncDetector mPrimarySyncDetector;
|
||||
@@ -146,7 +149,7 @@ public class P25P1SyncDetector implements Listener<Dibit>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncLost()
|
||||
public void syncLost(int bitsProcessed)
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.encryption.EncryptionKeyIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.encryption.APCO25EncryptionKey;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.reference.Encryption;
|
||||
import io.github.dsheirer.module.decode.p25.reference.Vendor;
|
||||
|
||||
@@ -154,7 +154,7 @@ public class HeaderData
|
||||
{
|
||||
if(mTalkgroup == null)
|
||||
{
|
||||
mTalkgroup = APCO25ToTalkgroup.createGroup(getMessage().getInt(TALKGROUP_ID));
|
||||
mTalkgroup = APCO25Talkgroup.create(getMessage().getInt(TALKGROUP_ID));
|
||||
}
|
||||
|
||||
return mTalkgroup;
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola;
|
||||
@@ -25,8 +27,7 @@ import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25AnyTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -64,7 +65,7 @@ public class LCMotorolaPatchGroupAdd extends MotorolaLinkControlWord
|
||||
{
|
||||
if(mPatchGroup == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25AnyTalkgroup.create(getMessage().getInt(PATCH_GROUP)));
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getMessage().getInt(PATCH_GROUP)));
|
||||
patchGroup.addPatchedGroups(getPatchedGroups());
|
||||
mPatchGroup = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
@@ -96,7 +97,7 @@ public class LCMotorolaPatchGroupAdd extends MotorolaLinkControlWord
|
||||
{
|
||||
if(mPatchedGroup1 == null)
|
||||
{
|
||||
mPatchedGroup1 = APCO25ToTalkgroup.createGroup(getMessage().getInt(PATCHED_GROUP_1));
|
||||
mPatchedGroup1 = APCO25Talkgroup.create(getMessage().getInt(PATCHED_GROUP_1));
|
||||
}
|
||||
|
||||
return mPatchedGroup1;
|
||||
@@ -115,7 +116,7 @@ public class LCMotorolaPatchGroupAdd extends MotorolaLinkControlWord
|
||||
{
|
||||
if(mPatchedGroup2 == null)
|
||||
{
|
||||
mPatchedGroup2 = APCO25ToTalkgroup.createGroup(getMessage().getInt(PATCHED_GROUP_2));
|
||||
mPatchedGroup2 = APCO25Talkgroup.create(getMessage().getInt(PATCHED_GROUP_2));
|
||||
}
|
||||
|
||||
return mPatchedGroup2;
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola;
|
||||
@@ -25,7 +27,7 @@ import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -63,7 +65,7 @@ public class LCMotorolaPatchGroupDelete extends MotorolaLinkControlWord
|
||||
{
|
||||
if(mPatchGroup == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25ToTalkgroup.createGroup(getMessage().getInt(PATCH_GROUP)));
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getMessage().getInt(PATCH_GROUP)));
|
||||
patchGroup.addPatchedGroups(getPatchedGroups());
|
||||
mPatchGroup = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
@@ -95,7 +97,7 @@ public class LCMotorolaPatchGroupDelete extends MotorolaLinkControlWord
|
||||
{
|
||||
if(mPatchedGroup1 == null)
|
||||
{
|
||||
mPatchedGroup1 = APCO25ToTalkgroup.createGroup(getMessage().getInt(PATCHED_GROUP_1));
|
||||
mPatchedGroup1 = APCO25Talkgroup.create(getMessage().getInt(PATCHED_GROUP_1));
|
||||
}
|
||||
|
||||
return mPatchedGroup1;
|
||||
@@ -114,7 +116,7 @@ public class LCMotorolaPatchGroupDelete extends MotorolaLinkControlWord
|
||||
{
|
||||
if(mPatchedGroup2 == null)
|
||||
{
|
||||
mPatchedGroup2 = APCO25ToTalkgroup.createGroup(getMessage().getInt(PATCHED_GROUP_2));
|
||||
mPatchedGroup2 = APCO25Talkgroup.create(getMessage().getInt(PATCHED_GROUP_2));
|
||||
}
|
||||
|
||||
return mPatchedGroup2;
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola;
|
||||
@@ -26,7 +28,7 @@ import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -76,7 +78,7 @@ public class LCMotorolaPatchGroupVoiceChannelUpdate extends MotorolaLinkControlW
|
||||
{
|
||||
if(mPatchGroup == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25ToTalkgroup.createGroup(getMessage().getInt(PATCH_GROUP)));
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getMessage().getInt(PATCH_GROUP)));
|
||||
mPatchGroup = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola;
|
||||
@@ -24,8 +26,8 @@ import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.patch.APCO25PatchGroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25FromTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -80,7 +82,7 @@ public class LCMotorolaPatchGroupVoiceChannelUser extends MotorolaLinkControlWor
|
||||
{
|
||||
if(mGroupAddress == null)
|
||||
{
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25ToTalkgroup.createGroup(getMessage().getInt(PATCH_GROUP_ADDRESS)));
|
||||
PatchGroup patchGroup = new PatchGroup(APCO25Talkgroup.create(getMessage().getInt(PATCH_GROUP_ADDRESS)));
|
||||
mGroupAddress = APCO25PatchGroup.create(patchGroup);
|
||||
}
|
||||
|
||||
@@ -94,7 +96,7 @@ public class LCMotorolaPatchGroupVoiceChannelUser extends MotorolaLinkControlWor
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25FromTalkgroup.createIndividual(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25AnyTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -92,7 +94,7 @@ public class LCMotorolaTalkComplete extends LinkControlWord
|
||||
{
|
||||
if(mAddress == null)
|
||||
{
|
||||
mAddress = APCO25AnyTalkgroup.create(getMessage().getInt(ADDRESS));
|
||||
mAddress = APCO25Talkgroup.create(getMessage().getInt(ADDRESS));
|
||||
}
|
||||
|
||||
return mAddress;
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25FromTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -70,7 +71,7 @@ public class LCCallAlert extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25ToTalkgroup.createIndividual(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
@@ -83,7 +84,7 @@ public class LCCallAlert extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25FromTalkgroup.createIndividual(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25AnyTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -65,7 +67,7 @@ public class LCCallTermination extends LinkControlWord
|
||||
{
|
||||
if(mAddress == null)
|
||||
{
|
||||
mAddress = APCO25AnyTalkgroup.create(getMessage().getInt(ADDRESS));
|
||||
mAddress = APCO25Talkgroup.create(getMessage().getInt(ADDRESS));
|
||||
}
|
||||
|
||||
return mAddress;
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.ExtendedFunction;
|
||||
|
||||
@@ -86,7 +88,7 @@ public class LCExtendedFunctionCommand extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25ToTalkgroup.createIndividual(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25FromTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -69,7 +70,7 @@ public class LCGroupAffiliationQuery extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25ToTalkgroup.createIndividual(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
@@ -82,7 +83,7 @@ public class LCGroupAffiliationQuery extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25FromTalkgroup.createIndividual(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.standard;
|
||||
@@ -24,7 +26,7 @@ import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25Channel;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
@@ -119,7 +121,7 @@ public class LCGroupVoiceChannelUpdate extends LinkControlWord implements IFrequ
|
||||
{
|
||||
if(mTalkgroupA == null)
|
||||
{
|
||||
mTalkgroupA = APCO25ToTalkgroup.createGroup(getMessage().getInt(GROUP_ADDRESS_A));
|
||||
mTalkgroupA = APCO25Talkgroup.create(getMessage().getInt(GROUP_ADDRESS_A));
|
||||
}
|
||||
|
||||
return mTalkgroupA;
|
||||
@@ -129,7 +131,7 @@ public class LCGroupVoiceChannelUpdate extends LinkControlWord implements IFrequ
|
||||
{
|
||||
if(mTalkgroupB == null)
|
||||
{
|
||||
mTalkgroupB = APCO25ToTalkgroup.createGroup(getMessage().getInt(GROUP_ADDRESS_B));
|
||||
mTalkgroupB = APCO25Talkgroup.create(getMessage().getInt(GROUP_ADDRESS_B));
|
||||
}
|
||||
|
||||
return mTalkgroupB;
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.standard;
|
||||
@@ -24,7 +26,7 @@ import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.channel.IChannelDescriptor;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.channel.APCO25ExplicitChannel;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
|
||||
@@ -110,7 +112,7 @@ public class LCGroupVoiceChannelUpdateExplicit extends LinkControlWord implement
|
||||
{
|
||||
if(mTalkgroup == null)
|
||||
{
|
||||
mTalkgroup = APCO25ToTalkgroup.createGroup(getMessage().getInt(GROUP_ADDRESS));
|
||||
mTalkgroup = APCO25Talkgroup.create(getMessage().getInt(GROUP_ADDRESS));
|
||||
}
|
||||
|
||||
return mTalkgroup;
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.standard;
|
||||
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25FromTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
|
||||
|
||||
@@ -85,7 +87,7 @@ public class LCGroupVoiceChannelUser extends LinkControlWord
|
||||
{
|
||||
if(mGroupAddress == null)
|
||||
{
|
||||
mGroupAddress = APCO25ToTalkgroup.createGroup(getMessage().getInt(GROUP_ADDRESS));
|
||||
mGroupAddress = APCO25Talkgroup.create(getMessage().getInt(GROUP_ADDRESS));
|
||||
}
|
||||
|
||||
return mGroupAddress;
|
||||
@@ -98,7 +100,7 @@ public class LCGroupVoiceChannelUser extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25FromTalkgroup.createIndividual(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.p25.phase1.message.lc.standard;
|
||||
@@ -23,8 +25,7 @@ package io.github.dsheirer.module.decode.p25.phase1.message.lc.standard;
|
||||
import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.message.APCO25ShortDataMessage;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25FromTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -83,7 +84,7 @@ public class LCMessageUpdate extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25ToTalkgroup.createIndividual(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
@@ -96,7 +97,7 @@ public class LCMessageUpdate extends LinkControlWord
|
||||
{
|
||||
if(mSourceAddress == null)
|
||||
{
|
||||
mSourceAddress = APCO25FromTalkgroup.createIndividual(getMessage().getInt(SOURCE_ADDRESS));
|
||||
mSourceAddress = APCO25RadioIdentifier.createFrom(getMessage().getInt(SOURCE_ADDRESS));
|
||||
}
|
||||
|
||||
return mSourceAddress;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -26,7 +26,7 @@ import io.github.dsheirer.bits.BinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.encryption.EncryptionKeyIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.encryption.APCO25EncryptionKey;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25ToTalkgroup;
|
||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -84,7 +84,7 @@ public class LCProtectionParameterBroadcast extends LinkControlWord
|
||||
{
|
||||
if(mTargetAddress == null)
|
||||
{
|
||||
mTargetAddress = APCO25ToTalkgroup.createIndividual(getMessage().getInt(TARGET_ADDRESS));
|
||||
mTargetAddress = APCO25RadioIdentifier.createTo(getMessage().getInt(TARGET_ADDRESS));
|
||||
}
|
||||
|
||||
return mTargetAddress;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
@@ -42,12 +42,12 @@ import java.util.List;
|
||||
public class LCRFSSStatusBroadcastExplicit extends LinkControlWord implements IFrequencyBandReceiver
|
||||
{
|
||||
private static final int[] LRA = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] DOWNLINK_FREQUENCY_BAND = {16, 17, 18, 19};
|
||||
private static final int[] DOWNLINK_CHANNEL_NUMBER = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] UPLINK_FREQUENCY_BAND = {16, 17, 18, 19};
|
||||
private static final int[] UPLINK_CHANNEL_NUMBER = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] RFSS = {32, 33, 34, 35, 36, 37, 38, 39};
|
||||
private static final int[] SITE = {40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] UPLINK_FREQUENCY_BAND = {48, 49, 50, 51};
|
||||
private static final int[] UPLINK_CHANNEL_NUMBER = {52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
|
||||
private static final int[] DOWNLINK_FREQUENCY_BAND = {48, 49, 50, 51};
|
||||
private static final int[] DOWNLINK_CHANNEL_NUMBER = {52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
|
||||
private static final int[] SERVICE_CLASS = {64, 65, 66, 67, 68, 69, 70, 71};
|
||||
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user