aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Berndt <lukekb@gmail.com>2023-02-06 21:27:12 -0500
committerGitHub <noreply@github.com>2023-02-06 21:27:12 -0500
commit47c27ca6a2a888b2d89e8aad66d63303bf2a671b (patch)
tree671d6536bad9d8088239a54aa870f31d4534af08
parenta11e502cf39fd7e1144180bcfb40223f92b3fc91 (diff)
parent088ae9fc9b3992d1cca2bc069ed43b5c77639633 (diff)
Merge pull request #758 from tadscottsmith/multi-site-v1
Enable Multi-site mode features.
-rw-r--r--docs/CONFIGURE.md17
-rw-r--r--trunk-recorder/call.h2
-rw-r--r--trunk-recorder/call_concluder/call_concluder.cc9
-rw-r--r--trunk-recorder/call_impl.cc15
-rw-r--r--trunk-recorder/call_impl.h3
-rw-r--r--trunk-recorder/formatter.cc42
-rw-r--r--trunk-recorder/formatter.h1
-rw-r--r--trunk-recorder/gr_blocks/transmission_sink.cc2
-rw-r--r--[-rwxr-xr-x]trunk-recorder/main.cc120
-rw-r--r--trunk-recorder/recorders/p25_recorder_impl.cc1
-rw-r--r--trunk-recorder/source.cc10
-rw-r--r--trunk-recorder/state.h10
-rw-r--r--trunk-recorder/systems/system.h7
-rw-r--r--trunk-recorder/systems/system_impl.cc15
-rw-r--r--trunk-recorder/systems/system_impl.h8
-rw-r--r--trunk-recorder/talkgroup.cc8
-rw-r--r--trunk-recorder/talkgroup.h5
-rw-r--r--trunk-recorder/talkgroups.cc9
18 files changed, 266 insertions, 18 deletions
diff --git a/docs/CONFIGURE.md b/docs/CONFIGURE.md
index c2b292c6..9d0d104a 100644
--- a/docs/CONFIGURE.md
+++ b/docs/CONFIGURE.md
@@ -199,7 +199,14 @@ Here is a map of the different sections of the *config.json* file:
| decodeTPS | | false | **true** / **false** | [ Conventional systems only ] enable the Motorola Tactical Public Safety (aka FDNY Fireground) signaling decoder. |
| enabled | | true | **true** / **false** | control whether a configured system is enabled or disabled |
+#### System Object - Experimental Options
+| Key | Required | Default Value | Type | Description |
+| ---------------------- | :------: | ------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
+| multiSite | | false | **true** / **false** | Enables multiSite mode for this system |
+| multiSiteSystemName | | | string | The name of the system that this site belongs to. **This is required for SmartNet in Multi-Site mode.** |
+
+Multi-Site mode attempts to avoid recording duplicate calls being broadcasted on multiple sites. Trunk recorder will not record duplicate calls on the same talkgroup for systems that have multiSite enabled. To ensure that both calls belong to the same system, Trunk Recorder will verify that both sites have the same WACN for P25, or the same multiSiteSystemName for SmartNet. By default, trunk-recorder will record the call from the first site that it receives the grant on, and any additional grants for the same call on other sites will be ignored. If you want to to specify the preferred site for a specific talk group, you can specify the preffered NAC in decimal format in the talk group CSV file.
#### Plugin Object
@@ -382,12 +389,12 @@ The Trunk Record program really only uses the priority information and the Dec T
Here are the column headers and some sample data: NOTE: If you are adding the Priority to a RR csv, as well as changing order you must use a heading for the first column other than "Decimal" eg DEC for TR to detect you are supplying this layout.
-| DEC | HEX | Mode | Alpha Tag | Description | Tag | Group | Priority |
-|------|-----|------|--------------|----------------|----------------|----------|----------|
-| 101 | 065 | D | DCFD 01 Disp | 01 Dispatch | Fire Dispatch | Fire | 1 |
-| 2227 | 8b3 | D | DC StcarYard | Streetcar Yard | Transportation | Services | 3 |
-
+| DEC | HEX | Mode | Alpha Tag | Description | Tag | Group | Priority | PreferredNAC (optional) |
+|-----|-----|------|-----------|-------------|-----|-------|----------|----------|
+|101 | 065 | D | DCFD 01 Disp | 01 Dispatch | Fire Dispatch | Fire | 1 | 1000 |
+|2227 | 8b3 | D | DC StcarYard | Streetcar Yard | Transportation | Services | 3 | 1001 |
+ In Multi-Site mode, the preferred NAC for a specific talk group is used to specify the site you prefer the talk group to be recorded from.
## channelFile
diff --git a/trunk-recorder/call.h b/trunk-recorder/call.h
index ad9ce7a1..dd47267a 100644
--- a/trunk-recorder/call.h
+++ b/trunk-recorder/call.h
@@ -56,6 +56,8 @@ public:
virtual bool get_sigmf_recording() = 0;
virtual void set_state(State s) = 0;
virtual State get_state() = 0;
+ virtual void set_monitoring_state(MonitoringState s) = 0;
+ virtual MonitoringState get_monitoring_state() = 0;
virtual void set_phase2_tdma(bool m) = 0;
virtual bool get_phase2_tdma() = 0;
virtual void set_tdma_slot(int s) = 0;
diff --git a/trunk-recorder/call_concluder/call_concluder.cc b/trunk-recorder/call_concluder/call_concluder.cc
index ff891c2d..dbf17b39 100644
--- a/trunk-recorder/call_concluder/call_concluder.cc
+++ b/trunk-recorder/call_concluder/call_concluder.cc
@@ -255,6 +255,7 @@ Call_Data_t Call_Concluder::create_call_data(Call *call, System *sys, Config con
call_info.audio_type = "digital";
}
+
// loop through the transmission list, pull in things to fill in totals for call_info
// Using a for loop with iterator
for (std::vector<Transmission>::iterator it = call_info.transmission_list.begin(); it != call_info.transmission_list.end();) {
@@ -307,7 +308,12 @@ void Call_Concluder::conclude_call(Call *call, System *sys, Config config) {
Call_Data_t call_info = create_call_data(call, sys, config);
- if (call_info.transmission_list.size() == 0 && call_info.min_transmissions_removed == 0) {
+ if(call->get_state() == MONITORING && call->get_monitoring_state() == SUPERSEDED){
+ BOOST_LOG_TRIVIAL(info) << "[" << call_info.short_name << "]\t\033[0;34m" << call_info.call_num << "C\033[0m\tTG: " << call_info.talkgroup_display << "\tFreq: " << format_freq(call_info.freq) << "\tCall has been superseded. Removing files.";
+ remove_call_files(call_info);
+ return;
+ }
+ else if (call_info.transmission_list.size()== 0 && call_info.min_transmissions_removed == 0) {
BOOST_LOG_TRIVIAL(error) << "[" << call_info.short_name << "]\t\033[0;34m" << call_info.call_num << "C\033[0m\tTG: " << call_info.talkgroup_display << "\t Freq: " << format_freq(call_info.freq) << "\tNo Transmissions were recorded!";
return;
}
@@ -322,6 +328,7 @@ void Call_Concluder::conclude_call(Call *call, System *sys, Config config) {
return;
}
+
call_data_workers.push_back(std::async(std::launch::async, upload_call_worker, call_info));
}
diff --git a/trunk-recorder/call_impl.cc b/trunk-recorder/call_impl.cc
index 2a1a9f78..80689b29 100644
--- a/trunk-recorder/call_impl.cc
+++ b/trunk-recorder/call_impl.cc
@@ -35,6 +35,7 @@ Call_impl::Call_impl(long t, double f, System *s, Config c) {
stop_time = time(NULL);
last_update = time(NULL);
state = MONITORING;
+ monitoringState = UNSPECIFIED;
debug_recording = false;
sigmf_recording = false;
recorder = NULL;
@@ -63,6 +64,7 @@ Call_impl::Call_impl(TrunkMessage message, System *s, Config c) {
stop_time = time(NULL);
last_update = time(NULL);
state = MONITORING;
+ monitoringState = UNSPECIFIED;
debug_recording = false;
sigmf_recording = false;
recorder = NULL;
@@ -126,7 +128,7 @@ void Call_impl::conclude_call() {
// BOOST_LOG_TRIVIAL(info) << "conclude_call()";
stop_time = time(NULL);
- if (state == COMPLETED) {
+ if (state == COMPLETED || (state == MONITORING && monitoringState == SUPERSEDED)) {
final_length = recorder->get_current_length();
if (!recorder) {
@@ -145,7 +147,8 @@ void Call_impl::conclude_call() {
}
Call_Concluder::conclude_call(this, sys, config);
- } else {
+ }
+ else {
BOOST_LOG_TRIVIAL(error) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "Concluding call, but call state is not COMPLETED!";
}
}
@@ -255,6 +258,14 @@ State Call_impl::get_state() {
return state;
}
+void Call_impl::set_monitoring_state(MonitoringState s) {
+ monitoringState = s;
+}
+
+MonitoringState Call_impl::get_monitoring_state() {
+ return monitoringState;
+}
+
void Call_impl::set_encrypted(bool m) {
encrypted = m;
}
diff --git a/trunk-recorder/call_impl.h b/trunk-recorder/call_impl.h
index af400a11..797fd63b 100644
--- a/trunk-recorder/call_impl.h
+++ b/trunk-recorder/call_impl.h
@@ -58,6 +58,8 @@ public:
bool get_sigmf_recording();
void set_state(State s);
State get_state();
+ void set_monitoring_state(MonitoringState s);
+ MonitoringState get_monitoring_state();
void set_phase2_tdma(bool m);
bool get_phase2_tdma();
void set_tdma_slot(int s);
@@ -86,6 +88,7 @@ public:
protected:
State state;
+ MonitoringState monitoringState;
static long call_counter;
long call_num;
long talkgroup;
diff --git a/trunk-recorder/formatter.cc b/trunk-recorder/formatter.cc
index c0733375..38d6b41d 100644
--- a/trunk-recorder/formatter.cc
+++ b/trunk-recorder/formatter.cc
@@ -48,3 +48,45 @@ std::string format_state(State state) {
}
return boost::lexical_cast<std::string>(state);
}
+
+std::string format_state(State state, MonitoringState monitoringState) {
+ if (statusAsString) {
+ if (state == MONITORING){
+ if(monitoringState == UNSPECIFIED)
+ return "monitoring";
+ else if(monitoringState == UNKNOWN_TG)
+ return "monitoring : UNKNOWN TG";
+ else if(monitoringState == IGNORED_TG)
+ return "monitoring : IGNORED TG";
+ else if(monitoringState == NO_SOURCE)
+ return "monitoring : NO SOURCE COVERING FREQ";
+ else if(monitoringState == NO_RECORDER)
+ return "monitoring : NO RECORDER AVAILABLE";
+ else if(monitoringState == ENCRYPTED)
+ return "monitoring : ENCRYPTED";
+ else if(monitoringState == DUPLICATE)
+ return "monitoring : DUPLICATE";
+ else if(monitoringState == SUPERSEDED)
+ return "monitoring : SUPERSEDED";
+ else
+ return "monitoring";
+ }
+ else if (state == RECORDING)
+ return "recording";
+ else if (state == INACTIVE)
+ return "inactive";
+ else if (state == ACTIVE)
+ return "active";
+ else if (state == IDLE)
+ return "idle";
+ else if (state == COMPLETED)
+ return "completed";
+ else if (state == STOPPED)
+ return "stopped";
+ else if (state == AVAILABLE)
+ return "available";
+ return "Unknown";
+ }
+ return boost::lexical_cast<std::string>(state);
+}
+
diff --git a/trunk-recorder/formatter.h b/trunk-recorder/formatter.h
index f03e1428..c07f68b0 100644
--- a/trunk-recorder/formatter.h
+++ b/trunk-recorder/formatter.h
@@ -8,6 +8,7 @@
extern boost::format format_freq(double f);
extern boost::format FormatSamplingRate(float f);
extern std::string format_state(State state);
+extern std::string format_state(State state, MonitoringState monitoringState);
std::string get_frequency_format();
extern int frequency_format;
extern bool statusAsString;
diff --git a/trunk-recorder/gr_blocks/transmission_sink.cc b/trunk-recorder/gr_blocks/transmission_sink.cc
index 179a196c..b385c3ae 100644
--- a/trunk-recorder/gr_blocks/transmission_sink.cc
+++ b/trunk-recorder/gr_blocks/transmission_sink.cc
@@ -200,7 +200,7 @@ void transmission_sink::set_source(long src) {
gr::thread::scoped_lock guard(d_mutex);
if (curr_src_id == -1) {
-
+
BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << d_current_call_talkgroup_display << "\tFreq: " << format_freq(d_current_call_freq) << "\tUnit ID set via Control Channel, ext: " << src << "\tcurrent: " << curr_src_id << "\t samples: " << d_sample_count;
curr_src_id = src;
diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc
index 103512f5..9063ae03 100755..100644
--- a/trunk-recorder/main.cc
+++ b/trunk-recorder/main.cc
@@ -363,9 +363,10 @@ bool load_config(string config_file) {
system->set_xor_mask(sys_id, wacn, nac);
system->set_bandplan(node.second.get<std::string>("bandplan", "800_standard"));
system->set_bandfreq(800); // Default to 800
-
+
if (boost::starts_with(system->get_bandplan(), "400")) {
system->set_bandfreq(400);
+
}
system->set_bandplan_base(node.second.get<double>("bandplanBase", 0.0));
system->set_bandplan_high(node.second.get<double>("bandplanHigh", 0.0));
@@ -394,6 +395,10 @@ bool load_config(string config_file) {
BOOST_LOG_TRIVIAL(info) << "Maximum Call Duration (in seconds): " << system->get_max_duration();
system->set_min_tx_duration(node.second.get<double>("minTransmissionDuration", 0));
BOOST_LOG_TRIVIAL(info) << "Minimum Transmission Duration (in seconds): " << system->get_min_tx_duration();
+ system->set_multiSite(node.second.get<bool>("multiSite", false));
+ BOOST_LOG_TRIVIAL(info) << "Multiple Site System: " << system->get_multiSite();
+ system->set_multiSiteSystemName(node.second.get<std::string>("multiSiteSystemName", ""));
+ BOOST_LOG_TRIVIAL(info) << "Multiple Site System Name: " << system->get_multiSiteSystemName();
if (!system->get_compress_wav()) {
if ((system->get_api_key().length() > 0) || (system->get_bcfy_api_key().length() > 0)) {
@@ -634,6 +639,8 @@ bool start_recorder(Call *call, TrunkMessage message, System *sys) {
}
if (call->get_encrypted() == true || (talkgroup && (talkgroup->mode.compare("E") == 0 || talkgroup->mode.compare("TE") == 0 || talkgroup->mode.compare("DE") == 0))) {
+ call->set_state(MONITORING);
+ call->set_monitoring_state(ENCRYPTED);
if (sys->get_hideEncrypted() == false) {
BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[31mNot Recording: ENCRYPTED\u001b[0m ";
}
@@ -689,6 +696,8 @@ bool start_recorder(Call *call, TrunkMessage message, System *sys) {
plugman_setup_recorder(recorder);
recorder_found = true;
} else {
+ call->set_state(MONITORING);
+ // call->set_monitoring_state(NO_SOURCE);
recorder_found = false;
return false;
}
@@ -730,6 +739,8 @@ bool start_recorder(Call *call, TrunkMessage message, System *sys) {
}
if (!source_found) {
+ call->set_state(MONITORING);
+ call->set_monitoring_state(NO_SOURCE);
BOOST_LOG_TRIVIAL(error) << "[" << sys->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mNot Recording: no source covering Freq\u001b[0m";
return false;
}
@@ -803,13 +814,19 @@ void print_status() {
for (vector<Call *>::iterator it = calls.begin(); it != calls.end(); it++) {
Call *call = *it;
Recorder *recorder = call->get_recorder();
- BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\tElapsed: " << std::setw(4) << call->elapsed() << " State: " << format_state(call->get_state());
+
+ if (call->get_state() == MONITORING) {
+ BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m TG: " << call->get_talkgroup_display() << " Freq: " << format_freq(call->get_freq()) << " Elapsed: " << std::setw(4) << call->elapsed() << " State: " << format_state(call->get_state(), call->get_monitoring_state());
+ } else {
+ BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m TG: " << call->get_talkgroup_display() << " Freq: " << format_freq(call->get_freq()) << " Elapsed: " << std::setw(4) << call->elapsed() << " State: " << format_state(call->get_state());
+ }
if (recorder) {
BOOST_LOG_TRIVIAL(info) << "\t[ " << recorder->get_num() << " ] State: " << format_state(recorder->get_state());
}
}
+
BOOST_LOG_TRIVIAL(info) << "Recorders: ";
for (vector<Source *>::iterator it = sources.begin(); it != sources.end(); it++) {
@@ -962,8 +979,12 @@ void unit_location(System *sys, long source_id, long talkgroup_num) {
void handle_call_grant(TrunkMessage message, System *sys) {
bool call_found = false;
+ bool duplicate_grant = false;
+ bool superseding_grant = false;
bool recording_started [[maybe_unused]] = false;
+ Call *original_call;
+
/* Notes: it is possible for 2 Calls to exist for the same talkgroup on different freq. This happens when a Talkgroup starts on a freq
that current recorder can't retune to. In this case, the current orig Talkgroup reocrder will keep going on the old freq, while a new
recorder is start on a source that can cover that freq. This makes sure any of the remaining transmission that it is in the buffer
@@ -972,7 +993,14 @@ void handle_call_grant(TrunkMessage message, System *sys) {
going until it gets a termination flag.
*/
- // BOOST_LOG_TRIVIAL(info) << "TG: " << message.talkgroup << " sys num: "<< message.sys_num << " freq: " << message.freq << " TDMA Slot" << message.tdma_slot << " TDMA: " << message.phase2_tdma;
+ //BOOST_LOG_TRIVIAL(info) << "TG: " << message.talkgroup << " sys num: " << message.sys_num << " freq: " << message.freq << " TDMA Slot" << message.tdma_slot << " TDMA: " << message.phase2_tdma;
+
+ int message_prefferedNAC = 0;
+ Talkgroup *message_talkgroup = sys->find_talkgroup(message.talkgroup);
+ if (message_talkgroup) {
+ message_prefferedNAC = message_talkgroup->get_preferredNAC();
+ }
+ //BOOST_LOG_TRIVIAL(info) << "TG: " << message.talkgroup << " Preferred NAC: " << message_prefferedNAC << ".";
for (vector<Call *>::iterator it = calls.begin(); it != calls.end();) {
Call *call = *it;
@@ -983,6 +1011,56 @@ void handle_call_grant(TrunkMessage message, System *sys) {
continue;
}
+ if ((call->get_talkgroup() == message.talkgroup) && (call->get_phase2_tdma() == message.phase2_tdma)) {
+ if (call->get_sys_num() != message.sys_num) {
+ if (call->get_system()->get_multiSite() && sys->get_multiSite()) {
+ if (call->get_system()->get_wacn() == sys->get_wacn()) {
+ // Default mode to match WACN and NAC and use a preferred NAC;
+ if (call->get_system()->get_nac() != sys->get_nac() && (call->get_system()->get_multiSiteSystemName() == "")) {
+ if (call->get_state() == RECORDING) {
+
+ duplicate_grant = true;
+ original_call = call;
+
+ int call_prefferedNAC = 0;
+ Talkgroup *call_talkgroup = call->get_system()->find_talkgroup(message.talkgroup);
+ if (call_talkgroup) {
+ call_prefferedNAC = message_talkgroup->get_preferredNAC();
+ }
+
+ if ((call_prefferedNAC != call->get_system()->get_nac()) && (message_prefferedNAC == sys->get_nac())) {
+ superseding_grant = true;
+ }
+
+ }
+ }
+ // If a multiSiteSystemName has been manually entered;
+ // We already know that Call's system number does not match the message system number.
+ // In this case, we check that the multiSiteSystemName is present, and that the Call and System multiSiteSystemNames are the same.
+ else if ((call->get_system()->get_multiSiteSystemName() != "") && (call->get_system()->get_multiSiteSystemName() == sys->get_multiSiteSystemName())) {
+ if (call->get_state() == RECORDING) {
+
+ duplicate_grant = true;
+ original_call = call;
+
+ // This is a hack to use the preferred Sytem Number as the preferredNAC.
+ // Should investiage a method to add a preferred Site name when manually specifcying mutliSiteSystemName
+ int call_prefferedNAC = 0;
+ Talkgroup *call_talkgroup = call->get_system()->find_talkgroup(message.talkgroup);
+ if (call_talkgroup) {
+ call_prefferedNAC = message_talkgroup->get_preferredNAC();
+ }
+ if ((call_prefferedNAC != call->get_sys_num()) && (message_prefferedNAC == sys->get_sys_num())) {
+ superseding_grant = true;
+ }
+
+ }
+ }
+ }
+ }
+ }
+ }
+
if ((call->get_talkgroup() == message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) {
call_found = true;
@@ -1039,7 +1117,41 @@ void handle_call_grant(TrunkMessage message, System *sys) {
if (!call_found) {
Call *call = Call::make(message, sys, config);
- recording_started = start_recorder(call, message, sys);
+
+ Talkgroup *talkgroup = sys->find_talkgroup(call->get_talkgroup());
+
+ if (talkgroup) {
+ call->set_talkgroup_tag(talkgroup->alpha_tag);
+ } else {
+ call->set_talkgroup_tag("-");
+ }
+
+
+ if(superseding_grant) {
+ BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << original_call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mSuperseding Grant. Original Call NAC: " << original_call->get_system()->get_nac() << " Grant Message NAC: " << sys->get_nac() << "\t State: " << format_state(original_call->get_state()) << "\u001b[0m";
+
+ // Attempt to start a new call on the preferred NAC.
+ recording_started = start_recorder(call, message, sys);
+
+ if(recording_started) {
+ // Clean up the original call.
+ original_call->set_state(MONITORING);
+ original_call->set_monitoring_state(SUPERSEDED);
+ original_call->conclude_call();
+ }
+ else{
+ BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << original_call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mCould not start Superseding recorder. Continuing original call: " << original_call->get_call_num() << "C\u001b[0m";
+ }
+ }
+ else if (duplicate_grant) {
+ call->set_state(MONITORING);
+ call->set_monitoring_state(DUPLICATE);
+ BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << original_call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mDuplicate Grant. Original Call NAC: " << original_call->get_system()->get_nac() << " Grant Message NAC: " << sys->get_nac() << " Source: " << message.source << " Call: " << original_call->get_call_num() << "C State: " << format_state(original_call->get_state()) << "\u001b[0m";
+ }
+ else {
+ recording_started = start_recorder(call, message, sys);
+ }
+
calls.push_back(call);
plugman_call_start(call);
plugman_calls_active(calls);
diff --git a/trunk-recorder/recorders/p25_recorder_impl.cc b/trunk-recorder/recorders/p25_recorder_impl.cc
index 0cf024ef..07a3547d 100644
--- a/trunk-recorder/recorders/p25_recorder_impl.cc
+++ b/trunk-recorder/recorders/p25_recorder_impl.cc
@@ -430,6 +430,7 @@ void p25_recorder_impl::stop() {
recording_duration += fsk4_p25_decode->get_current_length();
}
clear();
+
BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << this->call->get_talkgroup_display() << "\tFreq: " << format_freq(chan_freq) << "\t\u001b[33mStopping P25 Recorder Num [" << rec_num << "]\u001b[0m\tTDMA: " << d_phase2_tdma << "\tSlot: " << tdma_slot << "\tHz Error: " << this->get_freq_error();
state = INACTIVE;
diff --git a/trunk-recorder/source.cc b/trunk-recorder/source.cc
index ac197824..ecf6a03e 100644
--- a/trunk-recorder/source.cc
+++ b/trunk-recorder/source.cc
@@ -158,11 +158,15 @@ Recorder *Source::get_analog_recorder(Talkgroup *talkgroup, int priority, Call *
int num_available_recorders = get_num_available_analog_recorders();
if(talkgroup && (priority == -1)){
+ call->set_state(MONITORING);
+ call->set_monitoring_state(IGNORED_TG);
BOOST_LOG_TRIVIAL(info) << "[" << call->get_system()->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\tNot recording talkgroup. Priority is -1.";
return NULL;
}
if (talkgroup && priority > num_available_recorders) { // a high priority is bad. You need at least the number of availalbe recorders to your priority
+ call->set_state(MONITORING);
+ call->set_monitoring_state(NO_RECORDER);
BOOST_LOG_TRIVIAL(error) << "[" << call->get_system()->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\tNot recording talkgroup. Priority is " << priority << " but only " << num_available_recorders << " recorders are available.";
return NULL;
}
@@ -364,11 +368,15 @@ Recorder *Source::get_digital_recorder(Talkgroup *talkgroup, int priority, Call
int num_available_recorders = get_num_available_digital_recorders();
if(talkgroup && (priority == -1)){
+ call->set_state(MONITORING);
+ call->set_monitoring_state(IGNORED_TG);
BOOST_LOG_TRIVIAL(info) << "[" << call->get_system()->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\tNot recording talkgroup. Priority is -1.";
return NULL;
}
if (talkgroup && priority > num_available_recorders) { // a high priority is bad. You need at least the number of availalbe recorders to your priority
+ call->set_state(MONITORING);
+ call->set_monitoring_state(NO_RECORDER);
BOOST_LOG_TRIVIAL(error) << "[" << call->get_system()->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\tNot recording talkgroup. Priority is " << priority << " but only " << num_available_recorders << " recorders are available.";
return NULL;
}
@@ -388,6 +396,8 @@ Recorder *Source::get_digital_recorder(Call *call) {
}
}
+ return NULL;
+
BOOST_LOG_TRIVIAL(error) << "[" << call->get_system()->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t[ " << device << " ] No Digital Recorders Available.";
for (std::vector<p25_recorder_sptr>::iterator it = digital_recorders.begin();
diff --git a/trunk-recorder/state.h b/trunk-recorder/state.h
index f0b387c2..e1d29f4e 100644
--- a/trunk-recorder/state.h
+++ b/trunk-recorder/state.h
@@ -10,4 +10,14 @@ enum State { MONITORING = 0,
STOPPED = 6,
AVAILABLE = 7 };
+enum MonitoringState {
+ UNSPECIFIED = 0,
+ UNKNOWN_TG = 1,
+ IGNORED_TG = 2,
+ NO_SOURCE = 3,
+ NO_RECORDER = 4,
+ ENCRYPTED = 5,
+ DUPLICATE = 6,
+ SUPERSEDED = 7};
+
#endif
diff --git a/trunk-recorder/systems/system.h b/trunk-recorder/systems/system.h
index 5f4b4b66..117bd093 100644
--- a/trunk-recorder/systems/system.h
+++ b/trunk-recorder/systems/system.h
@@ -159,5 +159,12 @@ public:
virtual void update_active_talkgroup_patches(PatchData f_data) = 0;
virtual void delete_talkgroup_patch(PatchData f_data) = 0;
virtual void clear_stale_talkgroup_patches() = 0;
+
+ virtual bool get_multiSite() = 0;
+ virtual void set_multiSite(bool multiSite) = 0;
+
+ virtual std::string get_multiSiteSystemName() = 0;
+ virtual void set_multiSiteSystemName(std::string multiSiteSystemName) = 0;
+
};
#endif
diff --git a/trunk-recorder/systems/system_impl.cc b/trunk-recorder/systems/system_impl.cc
index 02606ed5..b6488fa2 100644
--- a/trunk-recorder/systems/system_impl.cc
+++ b/trunk-recorder/systems/system_impl.cc
@@ -591,3 +591,18 @@ void System_impl::clear_stale_talkgroup_patches() {
BOOST_LOG_TRIVIAL(debug) << "Active Patch of TGIDs" << printstring;
}
}
+
+bool System_impl::get_multiSite() {
+ return d_multiSite;
+}
+void System_impl::set_multiSite(bool multiSite) {
+ d_multiSite = multiSite;
+}
+
+std::string System_impl::get_multiSiteSystemName() {
+ return d_multiSiteSystemName;
+}
+
+void System_impl::set_multiSiteSystemName(std::string multiSiteSystemName) {
+ d_multiSiteSystemName = multiSiteSystemName;
+} \ No newline at end of file
diff --git a/trunk-recorder/systems/system_impl.h b/trunk-recorder/systems/system_impl.h
index 24c042cb..216f1842 100644
--- a/trunk-recorder/systems/system_impl.h
+++ b/trunk-recorder/systems/system_impl.h
@@ -218,10 +218,18 @@ public:
void delete_talkgroup_patch(PatchData f_data);
void clear_stale_talkgroup_patches();
+ bool get_multiSite();
+ void set_multiSite(bool multiSite);
+
+ std::string get_multiSiteSystemName();
+ void set_multiSiteSystemName(std::string multiSiteSystemName);
+
private:
TalkgroupDisplayFormat talkgroup_display_format;
bool d_hideEncrypted;
bool d_hideUnknown;
+ bool d_multiSite;
+ std::string d_multiSiteSystemName;
bool d_mdc_enabled;
bool d_fsync_enabled;
diff --git a/trunk-recorder/talkgroup.cc b/trunk-recorder/talkgroup.cc
index f0c1ec5c..5c648c57 100644
--- a/trunk-recorder/talkgroup.cc
+++ b/trunk-recorder/talkgroup.cc
@@ -1,6 +1,6 @@
#include "talkgroup.h"
-Talkgroup::Talkgroup(int sys_num, long num, std::string mode, std::string alpha_tag, std::string description, std::string tag, std::string group, int priority) {
+Talkgroup::Talkgroup(int sys_num, long num, std::string mode, std::string alpha_tag, std::string description, std::string tag, std::string group, int priority, int prefferedNAC) {
this->sys_num = sys_num;
this->number = num;
this->mode = mode;
@@ -12,6 +12,7 @@ Talkgroup::Talkgroup(int sys_num, long num, std::string mode, std::string alpha_
this->active = false;
this->freq = 0;
this->tone = 0;
+ this->prefferedNAC = prefferedNAC;
}
Talkgroup::Talkgroup(int sys_num, long num, double freq, double tone, std::string alpha_tag, std::string description, std::string tag, std::string group) {
@@ -26,6 +27,7 @@ Talkgroup::Talkgroup(int sys_num, long num, double freq, double tone, std::strin
this->freq = freq;
this->tone = tone;
this->priority = 0;
+ this->prefferedNAC = 0;
}
std::string Talkgroup::menu_string() {
@@ -46,6 +48,10 @@ int Talkgroup::get_priority() {
return priority;
}
+int Talkgroup::get_preferredNAC() {
+ return prefferedNAC;
+}
+
void Talkgroup::set_priority(int new_priority) {
priority = new_priority;
return;
diff --git a/trunk-recorder/talkgroup.h b/trunk-recorder/talkgroup.h
index 16052733..33e1981a 100644
--- a/trunk-recorder/talkgroup.h
+++ b/trunk-recorder/talkgroup.h
@@ -17,20 +17,23 @@ public:
int priority;
int sys_num;
+
// For Conventional
double freq;
double tone;
- Talkgroup(int sys_num, long num, std::string mode, std::string alpha_tag, std::string description, std::string tag, std::string group, int priority);
+ Talkgroup(int sys_num, long num, std::string mode, std::string alpha_tag, std::string description, std::string tag, std::string group, int priority, int preferredNAC);
Talkgroup(int sys_num, long num, double freq, double tone, std::string alpha_tag, std::string description, std::string tag, std::string group);
bool is_active();
int get_priority();
+ int get_preferredNAC();
void set_priority(int new_priority);
void set_active(bool a);
std::string menu_string();
private:
+ int prefferedNAC;
bool active;
};
diff --git a/trunk-recorder/talkgroups.cc b/trunk-recorder/talkgroups.cc
index 7c1c75c6..9197b77f 100644
--- a/trunk-recorder/talkgroups.cc
+++ b/trunk-recorder/talkgroups.cc
@@ -75,7 +75,8 @@ void Talkgroups::load_talkgroups(int sys_num, std::string filename) {
continue;
}
- tg = new Talkgroup(sys_num, atoi(vec[0].c_str()), vec[3].c_str(), vec[2].c_str(), vec[4].c_str(), vec[5].c_str(), vec[6].c_str(), 1);
+ tg = new Talkgroup(sys_num, atoi(vec[0].c_str()), vec[3].c_str(), vec[2].c_str(), vec[4].c_str(), vec[5].c_str(), vec[6].c_str(), 1, 0);
+
} else {
// Talkgroup configuration columns:
//
@@ -88,14 +89,16 @@ void Talkgroups::load_talkgroups(int sys_num, std::string filename) {
// [6] - group
// [7] - priority
- if (!((vec.size() == 8) || (vec.size() == 7))) {
+ if (!((vec.size() == 9) || (vec.size() == 8) || (vec.size() == 7))) {
BOOST_LOG_TRIVIAL(error) << "Malformed talkgroup entry at line " << lines_read << ".";
continue;
}
// TODO(nkw): more sanity checking here.
priority = (vec.size() == 8) ? atoi(vec[7].c_str()) : 1;
+ int preferredNAC = (vec.size() == 9) ? atoi(vec[8].c_str()) : 0;
+
+ tg = new Talkgroup(sys_num, atoi(vec[0].c_str()), vec[2].c_str(), vec[3].c_str(), vec[4].c_str(), vec[5].c_str(), vec[6].c_str(), priority, preferredNAC);
- tg = new Talkgroup(sys_num, atoi(vec[0].c_str()), vec[2].c_str(), vec[3].c_str(), vec[4].c_str(), vec[5].c_str(), vec[6].c_str(), priority);
}
talkgroups.push_back(tg);
lines_pushed++;