ReflectorLogic: QSY on squelch activity
Follow a remote initiated QSY on squelch open some short time after missing out on a QSY due to no local activity. Use configuration variable QSY_PENDING_TIMEOUT to set the time. Also, go to TG #0 immediately on ignored or pending QSY
This commit is contained in:
parent
7a843f549c
commit
c3c591a7c9
|
|
@ -260,7 +260,7 @@ blocks:
|
|||
alias: ''
|
||||
begin_tag: pmt.PMT_NIL
|
||||
comment: ''
|
||||
file: /tmp/rtl_vx6.raw
|
||||
file: file
|
||||
length: '0'
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
|
|
@ -428,6 +428,23 @@ blocks:
|
|||
coordinate: [24, 580.0]
|
||||
rotation: 0
|
||||
state: enabled
|
||||
- name: file
|
||||
id: parameter
|
||||
parameters:
|
||||
alias: ''
|
||||
comment: ''
|
||||
hide: none
|
||||
label: File
|
||||
short_id: f
|
||||
type: str
|
||||
value: /dev/zero
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [872, 12.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: qtgui_freq_sink_x_0
|
||||
id: qtgui_freq_sink_x
|
||||
parameters:
|
||||
|
|
@ -460,7 +477,7 @@ blocks:
|
|||
comment: ''
|
||||
ctrlpanel: 'False'
|
||||
fc: '0'
|
||||
fftsize: '1024'
|
||||
fftsize: '2048'
|
||||
freqhalf: 'False'
|
||||
grid: 'True'
|
||||
gui_hint: ''
|
||||
|
|
@ -498,7 +515,7 @@ blocks:
|
|||
width7: '1'
|
||||
width8: '1'
|
||||
width9: '1'
|
||||
wintype: firdes.WIN_RECTANGULAR
|
||||
wintype: firdes.WIN_BLACKMAN_hARRIS
|
||||
ymax: '10'
|
||||
ymin: '-110'
|
||||
states:
|
||||
|
|
|
|||
|
|
@ -651,7 +651,8 @@ priority.
|
|||
.B TG_SELECT_TIMEOUT
|
||||
The number of seconds after which a selected talk group will be unselected. The
|
||||
node will return to talk group 0 (no talk group) and start monitoring the
|
||||
configured talk groups again. Default: 30 seconds.
|
||||
configured talk groups again. The value must be larger than zero. Default: 30
|
||||
seconds.
|
||||
.TP
|
||||
.B ANNOUNCE_REMOTE_MIN_INTERVAL
|
||||
The minimum number of seconds between announcements of the same TG for remote
|
||||
|
|
@ -700,6 +701,15 @@ The number of seconds between UDP heartbeat messages sent to the reflector
|
|||
server. This configuration variable can normally be left at the default value
|
||||
but if you get frequent disconnects due to UDP heartbeat timeout it may help to
|
||||
lower this value. Default: 15
|
||||
.TP
|
||||
.B QSY_PENDING_TIMEOUT
|
||||
Set to the number of seconds to enable following a QSY request on squelch
|
||||
activity. That is, after a remote QSY request, during the configured number of
|
||||
seconds, it will be possible to follow a QSY request by just pushing the PTT
|
||||
instead of having to use DTMF commands. Note that the timer starts when the QSY
|
||||
request is received so the time it takes to play the QSY announcement is also
|
||||
included in the timeout time. A good value is within 10 to 15 seconds.
|
||||
Default is -1 (disabled).
|
||||
.P
|
||||
It is also possible to set audio codec parameters using the same configuration
|
||||
variables as documented for networked receivers and transmitters. For example,
|
||||
|
|
|
|||
|
|
@ -105,6 +105,9 @@
|
|||
supposed to default to a timeout of 30 seconds if TIMEOUT is not set. That
|
||||
did not work though.
|
||||
|
||||
* ReflectorLogic: Use the QSY_PENDING_TIMEOUT configuration variable to enable
|
||||
following a just ignored QSY request on squelch open.
|
||||
|
||||
|
||||
|
||||
1.7.0 -- 01 Sep 2019
|
||||
|
|
|
|||
|
|
@ -138,7 +138,8 @@ ReflectorLogic::ReflectorLogic(Async::Config& cfg, const std::string& name)
|
|||
m_tg_local_activity(false), m_last_qsy(0), m_logic_con_in_valve(0),
|
||||
m_mute_first_tx_loc(true), m_mute_first_tx_rem(false),
|
||||
m_tmp_monitor_timer(1000, Async::Timer::TYPE_PERIODIC),
|
||||
m_tmp_monitor_timeout(DEFAULT_TMP_MONITOR_TIMEOUT), m_use_prio(true)
|
||||
m_tmp_monitor_timeout(DEFAULT_TMP_MONITOR_TIMEOUT), m_use_prio(true),
|
||||
m_qsy_pending_timer(-1)
|
||||
{
|
||||
m_reconnect_timer.expired.connect(
|
||||
sigc::hide(mem_fun(*this, &ReflectorLogic::reconnect)));
|
||||
|
|
@ -154,6 +155,8 @@ ReflectorLogic::ReflectorLogic(Async::Config& cfg, const std::string& name)
|
|||
sigc::mem_fun(*this, &ReflectorLogic::processTgSelectionEvent)));
|
||||
m_tmp_monitor_timer.expired.connect(sigc::hide(
|
||||
sigc::mem_fun(*this, &ReflectorLogic::checkTmpMonitorTimeout)));
|
||||
m_qsy_pending_timer.expired.connect(sigc::hide(
|
||||
sigc::mem_fun(*this, &ReflectorLogic::qsyPendingTimeout)));
|
||||
} /* ReflectorLogic::ReflectorLogic */
|
||||
|
||||
|
||||
|
|
@ -293,7 +296,22 @@ bool ReflectorLogic::initialize(void)
|
|||
prev_src = 0;
|
||||
|
||||
cfg().getValue(name(), "DEFAULT_TG", m_default_tg);
|
||||
cfg().getValue(name(), "TG_SELECT_TIMEOUT", m_tg_select_timeout);
|
||||
if (!cfg().getValue(name(), "TG_SELECT_TIMEOUT", 1U,
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
m_tg_select_timeout, true))
|
||||
{
|
||||
std::cout << "*** ERROR[" << name()
|
||||
<< "]: Illegal value (" << m_tg_select_timeout
|
||||
<< ") for TG_SELECT_TIMEOUT" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
int qsy_pending_timeout = -1;
|
||||
if (cfg().getValue(name(), "QSY_PENDING_TIMEOUT", qsy_pending_timeout) &&
|
||||
(qsy_pending_timeout > 0))
|
||||
{
|
||||
m_qsy_pending_timer.setTimeout(1000 * qsy_pending_timeout);
|
||||
}
|
||||
|
||||
m_event_handler = new EventHandler(event_handler_str, name());
|
||||
if (LinkManager::hasInstance())
|
||||
|
|
@ -1116,10 +1134,24 @@ void ReflectorLogic::handleMsgRequestQsy(std::istream& is)
|
|||
else
|
||||
{
|
||||
m_last_qsy = msg.tg();
|
||||
cout << name()
|
||||
<< ": Server QSY request ignored. No local activity." << endl;
|
||||
selectTg(0, "", false);
|
||||
std::ostringstream os;
|
||||
os << "tg_qsy_ignored " << msg.tg();
|
||||
if (m_qsy_pending_timer.timeout() > 0)
|
||||
{
|
||||
cout << name() << ": Server QSY request pending" << endl;
|
||||
os << "tg_qsy_pending " << msg.tg();
|
||||
m_qsy_pending_timer.setEnable(true);
|
||||
m_use_prio = false;
|
||||
m_tg_select_timeout_cnt = 1 + m_qsy_pending_timer.timeout() / 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << name()
|
||||
<< ": Server QSY request ignored due to no local activity" << endl;
|
||||
os << "tg_qsy_ignored " << msg.tg();
|
||||
m_use_prio = true;
|
||||
m_tg_select_timeout_cnt = 0;
|
||||
}
|
||||
processEvent(os.str());
|
||||
}
|
||||
} /* ReflectorLogic::handleMsgRequestQsy */
|
||||
|
|
@ -1505,6 +1537,16 @@ void ReflectorLogic::onLogicConInStreamStateChanged(bool is_active,
|
|||
{
|
||||
m_logic_con_in_valve->setOpen(true);
|
||||
}
|
||||
if (m_qsy_pending_timer.isEnabled())
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "tg_qsy_on_sql " << m_last_qsy;
|
||||
processEvent(os.str());
|
||||
selectTg(m_last_qsy, "", true);
|
||||
m_qsy_pending_timer.setEnable(false);
|
||||
m_tg_local_activity = true;
|
||||
m_use_prio = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1515,6 +1557,7 @@ void ReflectorLogic::onLogicConInStreamStateChanged(bool is_active,
|
|||
selectTg(m_default_tg, "tg_default_activation", !m_mute_first_tx_loc);
|
||||
}
|
||||
}
|
||||
m_qsy_pending_timer.reset();
|
||||
m_tg_local_activity = true;
|
||||
m_use_prio = false;
|
||||
m_tg_select_timeout_cnt = m_tg_select_timeout;
|
||||
|
|
@ -1567,11 +1610,14 @@ void ReflectorLogic::selectTg(uint32_t tg, const std::string& event, bool unmute
|
|||
{
|
||||
cout << name() << ": Selecting TG #" << tg << endl;
|
||||
|
||||
ostringstream os;
|
||||
os << event << " " << tg << " " << m_selected_tg;
|
||||
m_tg_selection_event = os.str();
|
||||
m_report_tg_timer.reset();
|
||||
m_report_tg_timer.setEnable(true);
|
||||
if (!event.empty())
|
||||
{
|
||||
ostringstream os;
|
||||
os << event << " " << tg << " " << m_selected_tg;
|
||||
m_tg_selection_event = os.str();
|
||||
m_report_tg_timer.reset();
|
||||
m_report_tg_timer.setEnable(true);
|
||||
}
|
||||
|
||||
if (tg != m_selected_tg)
|
||||
{
|
||||
|
|
@ -1589,6 +1635,7 @@ void ReflectorLogic::selectTg(uint32_t tg, const std::string& event, bool unmute
|
|||
else
|
||||
{
|
||||
m_tg_local_activity = !m_logic_con_in->isIdle();
|
||||
m_qsy_pending_timer.setEnable(false);
|
||||
}
|
||||
m_event_handler->setVariable(name() + "::selected_tg", m_selected_tg);
|
||||
m_event_handler->setVariable(name() + "::previous_tg", m_previous_tg);
|
||||
|
|
@ -1653,6 +1700,19 @@ void ReflectorLogic::checkTmpMonitorTimeout(void)
|
|||
} /* ReflectorLogic::checkTmpMonitorTimeout */
|
||||
|
||||
|
||||
void ReflectorLogic::qsyPendingTimeout(void)
|
||||
{
|
||||
m_qsy_pending_timer.setEnable(false);
|
||||
m_use_prio = true;
|
||||
m_tg_select_timeout_cnt = 0;
|
||||
cout << name()
|
||||
<< ": Server QSY request ignored due to no local activity" << endl;
|
||||
std::ostringstream os;
|
||||
os << "tg_qsy_ignored " << m_last_qsy;
|
||||
processEvent(os.str());
|
||||
} /* ReflectorLogic::qsyPendingTimeout */
|
||||
|
||||
|
||||
/*
|
||||
* This file has not been truncated
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -205,11 +205,11 @@ class ReflectorLogic : public LogicBase
|
|||
typedef std::set<MonitorTgEntry> MonitorTgsSet;
|
||||
|
||||
static const unsigned DEFAULT_UDP_HEARTBEAT_TX_CNT_RESET = 15;
|
||||
static const unsigned UDP_HEARTBEAT_RX_CNT_RESET = 60;
|
||||
static const unsigned TCP_HEARTBEAT_TX_CNT_RESET = 10;
|
||||
static const unsigned TCP_HEARTBEAT_RX_CNT_RESET = 15;
|
||||
static const unsigned DEFAULT_TG_SELECT_TIMEOUT = 30;
|
||||
static const int DEFAULT_TMP_MONITOR_TIMEOUT = 3600;
|
||||
static const unsigned UDP_HEARTBEAT_RX_CNT_RESET = 60;
|
||||
static const unsigned TCP_HEARTBEAT_TX_CNT_RESET = 10;
|
||||
static const unsigned TCP_HEARTBEAT_RX_CNT_RESET = 15;
|
||||
static const unsigned DEFAULT_TG_SELECT_TIMEOUT = 30;
|
||||
static const int DEFAULT_TMP_MONITOR_TIMEOUT = 3600;
|
||||
|
||||
std::string m_reflector_host;
|
||||
uint16_t m_reflector_port;
|
||||
|
|
@ -255,6 +255,7 @@ class ReflectorLogic : public LogicBase
|
|||
Async::Timer m_tmp_monitor_timer;
|
||||
int m_tmp_monitor_timeout;
|
||||
bool m_use_prio;
|
||||
Async::Timer m_qsy_pending_timer;
|
||||
|
||||
ReflectorLogic(const ReflectorLogic&);
|
||||
ReflectorLogic& operator=(const ReflectorLogic&);
|
||||
|
|
@ -297,6 +298,7 @@ class ReflectorLogic : public LogicBase
|
|||
void processEvent(const std::string& event);
|
||||
void processTgSelectionEvent(void);
|
||||
void checkTmpMonitorTimeout(void);
|
||||
void qsyPendingTimeout(void);
|
||||
|
||||
}; /* class ReflectorLogic */
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ variable prev_announce_tg 0
|
|||
# Change through ANNOUNCE_REMOTE_MIN_INTERVAL config variable.
|
||||
variable announce_remote_min_interval 0
|
||||
|
||||
# This variable will be set to 1 if the QSY pending feature ("QSY on squelch
|
||||
# activity") is active. See configuration variable QSY_PENDING_TIMEOUT.
|
||||
variable qsy_pending_active 0
|
||||
|
||||
#
|
||||
# Checking to see if this is the correct logic core
|
||||
#
|
||||
|
|
@ -195,6 +199,17 @@ proc tg_qsy {new_tg old_tg} {
|
|||
}
|
||||
|
||||
|
||||
#
|
||||
# Executed when a QSY is followed due to squelch open (see QSY_PENDING_TIMEOUT)
|
||||
#
|
||||
# tg -- The talk group that has been activated
|
||||
#
|
||||
proc tg_qsy_on_sql {tg} {
|
||||
playSilence 100
|
||||
playMsg "Core" "qsy"
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Executed when a TG QSY request fails
|
||||
#
|
||||
|
|
@ -210,17 +225,37 @@ proc tg_qsy_failed {} {
|
|||
}
|
||||
|
||||
|
||||
#
|
||||
# Executed when a TG QSY request is pending
|
||||
#
|
||||
# tg -- The talk group requested in the QSY
|
||||
#
|
||||
proc tg_qsy_pending {tg} {
|
||||
playSilence 100
|
||||
playMsg "Core" "qsy"
|
||||
spellNumber $tg
|
||||
playMsg "Core" "pending"
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Executed when a TG QSY request is ignored
|
||||
#
|
||||
# tg -- The talk group requested in the QSY
|
||||
#
|
||||
proc tg_qsy_ignored {tg} {
|
||||
#puts "### tg_qsy_ignored"
|
||||
variable qsy_pending_active
|
||||
playSilence 100
|
||||
playMsg "Core" "qsy"
|
||||
spellNumber $tg
|
||||
if {!$qsy_pending_active} {
|
||||
playMsg "Core" "qsy"
|
||||
spellNumber $tg
|
||||
}
|
||||
playMsg "Core" "ignored"
|
||||
playSilence 500
|
||||
playTone 880 200 50
|
||||
playTone 659 200 50
|
||||
playTone 440 200 50
|
||||
playSilence 100
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -299,6 +334,12 @@ if [info exists ::Logic::CFG_ANNOUNCE_REMOTE_MIN_INTERVAL] {
|
|||
set announce_remote_min_interval $::Logic::CFG_ANNOUNCE_REMOTE_MIN_INTERVAL
|
||||
}
|
||||
|
||||
if [info exists ::Logic::CFG_QSY_PENDING_TIMEOUT] {
|
||||
if {$::Logic::CFG_QSY_PENDING_TIMEOUT > 0} {
|
||||
set qsy_pending_active 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# end of namespace
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ EVENT_HANDLER=@SVX_SHARE_INSTALL_DIR@/events.tcl
|
|||
#MUTE_FIRST_TX_REM=1
|
||||
#TMP_MONITOR_TIMEOUT=3600
|
||||
#UDP_HEARTBEAT_INTERVAL=15
|
||||
QSY_PENDING_TIMEOUT=10
|
||||
|
||||
[LinkToR4]
|
||||
CONNECT_LOGICS=RepeaterLogic:94:SK3AB,SimplexLogic:92:SK3CD
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ LIBECHOLIB=1.3.3
|
|||
LIBASYNC=1.6.99.12
|
||||
|
||||
# SvxLink versions
|
||||
SVXLINK=1.7.99.31
|
||||
SVXLINK=1.7.99.32
|
||||
MODULE_HELP=1.0.0
|
||||
MODULE_PARROT=1.1.1
|
||||
MODULE_ECHO_LINK=1.5.99.0
|
||||
|
|
|
|||
Loading…
Reference in New Issue