Jump to content

Hamradio/chan svx sat: Difference between revisions

From MediaWiki For Hamradio Analog/Digital and Debian v13 software/Raspberry PI v3/4/5 howto
Move to Hamradio (translation-ready)
 
Marked this version for translation
 
Line 3: Line 3:


<translate>
<translate>
<!--T:1-->
''A hand-held, step-by-step guide to bridging an '''AllStarLink 3''' node straight to a '''SVXReflector''' with '''chan_svx_sat''' — install it, get it connected, and get the audio right. No prior SvxLink knowledge needed. Copy-paste friendly.''
''A hand-held, step-by-step guide to bridging an '''AllStarLink 3''' node straight to a '''SVXReflector''' with '''chan_svx_sat''' — install it, get it connected, and get the audio right. No prior SvxLink knowledge needed. Copy-paste friendly.''


<!--T:2-->
<div style="border-left:4px solid #4da3ff; background:#13233a; padding:10px 16px; margin:14px 0; border-radius:6px;">💡 '''In one sentence:''' <code>chan_svx_sat</code> is an Asterisk channel driver that lets your AllStar node talk Opus directly to a SVXReflector — so you drop the old <code>chan_usrp</code> → svxlink hop and the extra vocoder tandem that came with it.</div>
<div style="border-left:4px solid #4da3ff; background:#13233a; padding:10px 16px; margin:14px 0; border-radius:6px;">💡 '''In one sentence:''' <code>chan_svx_sat</code> is an Asterisk channel driver that lets your AllStar node talk Opus directly to a SVXReflector — so you drop the old <code>chan_usrp</code> → svxlink hop and the extra vocoder tandem that came with it.</div>


<!--T:3-->
[[File:Chan_svx_sat_architecture.png|center|frameless|860px|alt=Before: app_rpt via USRP and svxlink to the reflector. After: app_rpt straight to the reflector over one Opus stream.]]
[[File:Chan_svx_sat_architecture.png|center|frameless|860px|alt=Before: app_rpt via USRP and svxlink to the reflector. After: app_rpt straight to the reflector over one Opus stream.]]
<div style="text-align:center; color:#9aa0a6; font-style:italic; margin:-6px 0 14px;">One Opus hop instead of two transcodes. Less latency, cleaner audio.</div>
<div style="text-align:center; color:#9aa0a6; font-style:italic; margin:-6px 0 14px;">One Opus hop instead of two transcodes. Less latency, cleaner audio.</div>


<!--T:4-->
__TOC__
__TOC__


== Do I even need this? ==
== Do I even need this? == <!--T:5-->


<!--T:6-->
* '''You run an AllStarLink 3 node''' (on a Raspberry Pi or x86) '''and''' you want it on a '''SVXReflector''' talkgroup.
* '''You run an AllStarLink 3 node''' (on a Raspberry Pi or x86) '''and''' you want it on a '''SVXReflector''' talkgroup.
* Today you probably bridge it with <code>chan_usrp</code> → <code>svxlink</code>. That works, but it transcodes the audio twice and adds a box to babysit.
* Today you probably bridge it with <code>chan_usrp</code> → <code>svxlink</code>. That works, but it transcodes the audio twice and adds a box to babysit.
* <code>chan_svx_sat</code> replaces that whole hop with '''one''' driver. The audio path becomes just PCM ↔ Opus, once.
* <code>chan_svx_sat</code> replaces that whole hop with '''one''' driver. The audio path becomes just PCM ↔ Opus, once.


<!--T:7-->
If you are '''not''' going to a SvxReflector — e.g. you only link AllStar-to-AllStar, or you use DMR/YSF — you don't need this. See [[Hamradio]] for those.
If you are '''not''' going to a SvxReflector — e.g. you only link AllStar-to-AllStar, or you use DMR/YSF — you don't need this. See [[Hamradio]] for those.


== Words you'll see (plain-language glossary) ==
== Words you'll see (plain-language glossary) == <!--T:8-->


<!--T:9-->
{| class="wikitable" style="width:100%;"
{| class="wikitable" style="width:100%;"
|-
|-
Line 41: Line 48:
|}
|}


== What you need before you start ==
== What you need before you start == <!--T:10-->


<!--T:11-->
<div style="border-left:4px solid #4da3ff; background:#13233a; padding:10px 16px; margin:14px 0; border-radius:6px;">💡 Tick all four. If one is missing, fix it first — the bridge can't work without them.</div>
<div style="border-left:4px solid #4da3ff; background:#13233a; padding:10px 16px; margin:14px 0; border-radius:6px;">💡 Tick all four. If one is missing, fix it first — the bridge can't work without them.</div>


<!--T:12-->
# '''A working AllStarLink 3 node.''' Check: <code>asterisk -V</code> shows <code>Asterisk 22.x+asl3-...</code>.
# '''A working AllStarLink 3 node.''' Check: <code>asterisk -V</code> shows <code>Asterisk 22.x+asl3-...</code>.
# '''A 64-bit OS.''' Debian 12 (bookworm) or 13 (trixie), on x86-64 or arm64 (Pi 3/4/5). Check: <code>dpkg --print-architecture</code> and <code>. /etc/os-release; echo $VERSION_CODENAME</code>. ''(The Pi Zero 2 W is intentionally not supported — heat + Wi-Fi.)''
# '''A 64-bit OS.''' Debian 12 (bookworm) or 13 (trixie), on x86-64 or arm64 (Pi 3/4/5). Check: <code>dpkg --print-architecture</code> and <code>. /etc/os-release; echo $VERSION_CODENAME</code>. ''(The Pi Zero 2 W is intentionally not supported — heat + Wi-Fi.)''
Line 50: Line 59:
# '''The reflector is reachable.''' Check: <code>nc -vz REFLECTOR_HOST 5300</code>.
# '''The reflector is reachable.''' Check: <code>nc -vz REFLECTOR_HOST 5300</code>.


<!--T:13-->
The worked example below is a real node: '''AllStar node 1999''' bridging to a reflector at '''172.16.1.1:5300''', talkgroup '''24016'''. Swap in your own host / login / TG everywhere you see them.
The worked example below is a real node: '''AllStar node 1999''' bridging to a reflector at '''172.16.1.1:5300''', talkgroup '''24016'''. Swap in your own host / login / TG everywhere you see them.


== How it all fits together ==
== How it all fits together == <!--T:14-->


<!--T:15-->
Two small config files on the node, and one matching <code>SECRET</code> line on the reflector. That is the entire wiring:
Two small config files on the node, and one matching <code>SECRET</code> line on the reflector. That is the entire wiring:


<!--T:16-->
[[File:Chan_svx_sat_topology.png|center|frameless|900px|alt=rpt.conf points at a section in svx_sat.conf, which logs in to the reflector whose SECRET must match.]]
[[File:Chan_svx_sat_topology.png|center|frameless|900px|alt=rpt.conf points at a section in svx_sat.conf, which logs in to the reflector whose SECRET must match.]]
<div style="text-align:center; color:#9aa0a6; font-style:italic; margin:-6px 0 14px;"><code>rpt.conf</code> → a section in <code>svx_sat.conf</code> → a login the reflector recognises.</div>
<div style="text-align:center; color:#9aa0a6; font-style:italic; margin:-6px 0 14px;"><code>rpt.conf</code> → a section in <code>svx_sat.conf</code> → a login the reflector recognises.</div>


== Step 1 — Install the package ==
== Step 1 — Install the package == <!--T:17-->


<!--T:18-->
Pick the <code>.deb</code> that matches your OS '''and''' architecture:
Pick the <code>.deb</code> that matches your OS '''and''' architecture:


<!--T:19-->
{| class="wikitable"
{| class="wikitable"
|-
|-
Line 76: Line 90:
|}
|}


<!--T:20-->
<pre>sudo apt install ./asl3-chan-svx-sat_<ver>~<os>_<arch>.deb</pre>
<pre>sudo apt install ./asl3-chan-svx-sat_<ver>~<os>_<arch>.deb</pre>


<!--T:21-->
Dependencies (<code>asl3-asterisk</code>, <code>libopus0</code>, <code>libssl3</code>) resolve automatically. The package installs the module, a sample config, this kind of documentation under <code>/usr/share/doc/asl3-chan-svx-sat/</code>, and adds a '''commented''' load line to <code>modules.conf</code> for you to enable in Step 4. '''Nothing loads or connects yet.'''
Dependencies (<code>asl3-asterisk</code>, <code>libopus0</code>, <code>libssl3</code>) resolve automatically. The package installs the module, a sample config, this kind of documentation under <code>/usr/share/doc/asl3-chan-svx-sat/</code>, and adds a '''commented''' load line to <code>modules.conf</code> for you to enable in Step 4. '''Nothing loads or connects yet.'''


== Step 2 — Create the reflector config ==
== Step 2 — Create the reflector config == <!--T:22-->


<!--T:23-->
Copy the sample and open it for editing:
Copy the sample and open it for editing:


<!--T:24-->
<pre>sudo cp /etc/asterisk/svx_sat.conf.sample /etc/asterisk/svx_sat.conf
<pre>sudo cp /etc/asterisk/svx_sat.conf.sample /etc/asterisk/svx_sat.conf
sudo chown asterisk:asterisk /etc/asterisk/svx_sat.conf
sudo chown asterisk:asterisk /etc/asterisk/svx_sat.conf
Line 89: Line 107:
sudoedit /etc/asterisk/svx_sat.conf</pre>
sudoedit /etc/asterisk/svx_sat.conf</pre>


<!--T:25-->
Make it look like this (name the section after the node — tidy and unambiguous):
Make it look like this (name the section after the node — tidy and unambiguous):


<!--T:26-->
<pre>[1999]
<pre>[1999]
host    = 172.16.1.1      ; reflector hostname or IP
host    = 172.16.1.1      ; reflector hostname or IP
Line 99: Line 119:
tg      = 24016            ; talkgroup to select (TX + primary RX)</pre>
tg      = 24016            ; talkgroup to select (TX + primary RX)</pre>


<!--T:27-->
<div style="border-left:4px solid #4da3ff; background:#13233a; padding:10px 16px; margin:14px 0; border-radius:6px;">💡 '''The login + password must match the reflector.''' On the reflector's <code>[SATELLITE]</code> section there must be a line <code>SECRET_SA7AUX-AC=CHANGE_ME</code> (case-sensitive). If you run the reflector too: add/change the <code>SECRET_</code> line and '''restart the reflector''' — it only reads secrets at startup.</div>
<div style="border-left:4px solid #4da3ff; background:#13233a; padding:10px 16px; margin:14px 0; border-radius:6px;">💡 '''The login + password must match the reflector.''' On the reflector's <code>[SATELLITE]</code> section there must be a line <code>SECRET_SA7AUX-AC=CHANGE_ME</code> (case-sensitive). If you run the reflector too: add/change the <code>SECRET_</code> line and '''restart the reflector''' — it only reads secrets at startup.</div>


<!--T:28-->
The <code>callsign</code> is shown as the node's name '''if it is free''' on the reflector right now; on a collision (or if left empty) it falls back to <code>ASL-<section></code> (e.g. <code>ASL-1999</code>), re-checked automatically as names free up.
The <code>callsign</code> is shown as the node's name '''if it is free''' on the reflector right now; on a collision (or if left empty) it falls back to <code>ASL-<section></code> (e.g. <code>ASL-1999</code>), re-checked automatically as names free up.


== Step 3 — Point the node at it ==
== Step 3 — Point the node at it == <!--T:29-->


<!--T:30-->
In <code>/etc/asterisk/rpt.conf</code>, in your node's stanza, '''comment out the old rxchannel — never delete it''' — and add the SVX line:
In <code>/etc/asterisk/rpt.conf</code>, in your node's stanza, '''comment out the old rxchannel — never delete it''' — and add the SVX line:


<!--T:31-->
<pre>[1999](node-main)
<pre>[1999](node-main)
; rxchannel = USRP/127.0.0.1:4001:4002  ; old bridge, kept so you can revert
; rxchannel = USRP/127.0.0.1:4001:4002  ; old bridge, kept so you can revert
rxchannel = SVXSAT/1999                  ; chan_svx_sat -> section [1999]</pre>
rxchannel = SVXSAT/1999                  ; chan_svx_sat -> section [1999]</pre>


<!--T:32-->
<div style="border-left:4px solid #4da3ff; background:#13233a; padding:10px 16px; margin:14px 0; border-radius:6px;">💡 '''Want it to survive package upgrades?''' Put the node stanza in <code>/etc/asterisk/custom/rpt.conf</code> instead — ASL3 includes that file and never overwrites it. Use the direct edit above for a quick change; use <code>custom/</code> if you want your config to survive <code>asl3-asterisk</code> updates cleanly.</div>
<div style="border-left:4px solid #4da3ff; background:#13233a; padding:10px 16px; margin:14px 0; border-radius:6px;">💡 '''Want it to survive package upgrades?''' Put the node stanza in <code>/etc/asterisk/custom/rpt.conf</code> instead — ASL3 includes that file and never overwrites it. Use the direct edit above for a quick change; use <code>custom/</code> if you want your config to survive <code>asl3-asterisk</code> updates cleanly.</div>


== Step 4 — Enable the module ==
== Step 4 — Enable the module == <!--T:33-->


<!--T:34-->
ASL3 has <code>autoload = no</code>, so the module must be listed by hand. The package added a '''commented''' line — turn it on. '''It must live inside the <code>[modules]</code> section''' (a <code>load</code> line after a later section is silently ignored):
ASL3 has <code>autoload = no</code>, so the module must be listed by hand. The package added a '''commented''' line — turn it on. '''It must live inside the <code>[modules]</code> section''' (a <code>load</code> line after a later section is silently ignored):


<!--T:35-->
<pre>sudo sed -i 's/^; *load = chan_svx_sat.so/load = chan_svx_sat.so/' /etc/asterisk/modules.conf
<pre>sudo sed -i 's/^; *load = chan_svx_sat.so/load = chan_svx_sat.so/' /etc/asterisk/modules.conf
grep -n '^load = chan_svx_sat.so' /etc/asterisk/modules.conf    # confirm it's active</pre>
grep -n '^load = chan_svx_sat.so' /etc/asterisk/modules.conf    # confirm it's active</pre>


== Step 5 — Apply and verify ==
== Step 5 — Apply and verify == <!--T:36-->


<!--T:37-->
An <code>rxchannel</code> change needs app_rpt to re-init, so restart Asterisk, then check:
An <code>rxchannel</code> change needs app_rpt to re-init, so restart Asterisk, then check:


<!--T:38-->
<pre>sudo asterisk -rx "core restart now"
<pre>sudo asterisk -rx "core restart now"
sudo asterisk -rx "svxsat show"</pre>
sudo asterisk -rx "svxsat show"</pre>


<!--T:39-->
A healthy bridge looks like this — '''<code>CONNECTED</code> means you're done with the basic hookup''':
A healthy bridge looks like this — '''<code>CONNECTED</code> means you're done with the basic hookup''':


<!--T:40-->
[[File:Chan_svx_sat_svxsat_show.png|center|frameless|900px|alt=Annotated svxsat show output explaining CONNECTED, txframes, rxframes, starts/stops, fec and plc.]]
[[File:Chan_svx_sat_svxsat_show.png|center|frameless|900px|alt=Annotated svxsat show output explaining CONNECTED, txframes, rxframes, starts/stops, fec and plc.]]


<!--T:41-->
Key up on the node → <code>txframes</code> climbs and the reflector opens the talker on your TG. When someone else talks on the TG → <code>rxframes</code> climbs. Done. The rest of this page is tuning and extras.
Key up on the node → <code>txframes</code> climbs and the reflector opens the talker on your TG. When someone else talks on the TG → <code>rxframes</code> climbs. Done. The rest of this page is tuning and extras.


== Getting the audio right ==
== Getting the audio right == <!--T:42-->


<!--T:43-->
This is where most people get stuck, so take it slow. '''Only the yellow stages have knobs''' — everything grey is automatic.
This is where most people get stuck, so take it slow. '''Only the yellow stages have knobs''' — everything grey is automatic.


<!--T:44-->
[[File:Chan_svx_sat_audio_path.png|center|frameless|920px|alt=The TX and RX audio chains showing which stages are tunable (gain, AGC, jitter, tx_hold) and which are automatic (limiter, Opus FEC/PLC).]]
[[File:Chan_svx_sat_audio_path.png|center|frameless|920px|alt=The TX and RX audio chains showing which stages are tunable (gain, AGC, jitter, tx_hold) and which are automatic (limiter, Opus FEC/PLC).]]


<!--T:45-->
All of these live in the node's section in <code>svx_sat.conf</code>. '''After changing any of them, run <code>sudo asterisk -rx "core restart now"</code>.'''
All of these live in the node's section in <code>svx_sat.conf</code>. '''After changing any of them, run <code>sudo asterisk -rx "core restart now"</code>.'''


=== The four audio knobs ===
=== The four audio knobs === <!--T:46-->


<!--T:47-->
{| class="wikitable" style="width:100%;"
{| class="wikitable" style="width:100%;"
|-
|-
Line 156: Line 192:
|}
|}


<!--T:48-->
<div style="border-left:4px solid #4da3ff; background:#13233a; padding:10px 16px; margin:14px 0; border-radius:6px;">💡 A '''limiter is always on''' in both directions — it stops the audio clipping even if you raise the gain too far. '''Opus inband FEC + PLC''' are always on too: a lost packet is rebuilt from the next one's FEC, and an underrun is concealed instead of clicking. You don't configure any of that.</div>
<div style="border-left:4px solid #4da3ff; background:#13233a; padding:10px 16px; margin:14px 0; border-radius:6px;">💡 A '''limiter is always on''' in both directions — it stops the audio clipping even if you raise the gain too far. '''Opus inband FEC + PLC''' are always on too: a lost packet is rebuilt from the next one's FEC, and an underrun is concealed instead of clicking. You don't configure any of that.</div>


=== "My audio is X → do Y" ===
=== "My audio is X → do Y" === <!--T:49-->


<!--T:50-->
{| class="wikitable" style="width:100%;"
{| class="wikitable" style="width:100%;"
|-
|-
Line 177: Line 215:
|}
|}


=== Two more knobs: tx_hold and jitter ===
=== Two more knobs: tx_hold and jitter === <!--T:51-->


<!--T:52-->
{| class="wikitable" style="width:100%;"
{| class="wikitable" style="width:100%;"
|-
|-
Line 188: Line 227:
|}
|}


<!--T:53-->
<div id="The link flaps or chops"></div>
<div id="The link flaps or chops"></div>
'''If audio going out is chopped:''' run <code>svxsat show</code> and watch <code>starts</code>/<code>stops</code>. '''One each per over is healthy.''' Many per over means your key is flapping — raise <code>tx_hold</code> (try <code>400</code>).
'''If audio going out is chopped:''' run <code>svxsat show</code> and watch <code>starts</code>/<code>stops</code>. '''One each per over is healthy.''' Many per over means your key is flapping — raise <code>tx_hold</code> (try <code>400</code>).


=== Optional: listen to extra talkgroups ===
=== Optional: listen to extra talkgroups === <!--T:54-->


<!--T:55-->
<pre>monitor = 24020, 9990    ; extra TGs you HEAR (RX only); TX still goes to 'tg'</pre>
<pre>monitor = 24020, 9990    ; extra TGs you HEAR (RX only); TX still goes to 'tg'</pre>


== Keep it up — forever ==
== Keep it up — forever == <!--T:56-->


<!--T:57-->
Two independent things stay up: the '''reflector link''' and the '''AllStar node-to-node link'''.
Two independent things stay up: the '''reflector link''' and the '''AllStar node-to-node link'''.


<!--T:58-->
* '''The reflector link is automatic.''' chan_svx_sat reconnects on its own (TCP + UDP heartbeats, backoff after any drop). Nothing to configure; <code>svxsat show</code> goes back to <code>CONNECTED</code> within seconds of any outage.
* '''The reflector link is automatic.''' chan_svx_sat reconnects on its own (TCP + UDP heartbeats, backoff after any drop). Nothing to configure; <code>svxsat show</code> goes back to <code>CONNECTED</code> within seconds of any outage.
* '''Keep the AllStar node linked to a hub?''' Use app_rpt's permanent connect, which re-establishes itself:
* '''Keep the AllStar node linked to a hub?''' Use app_rpt's permanent connect, which re-establishes itself:


<!--T:59-->
<pre>sudo asterisk -rx "rpt cmd 1999 ilink 13 403870"  # 13 = permanent, transceive</pre>
<pre>sudo asterisk -rx "rpt cmd 1999 ilink 13 403870"  # 13 = permanent, transceive</pre>


<!--T:60-->
'''Link automatically at boot''' via the node stanza:
'''Link automatically at boot''' via the node stanza:


<!--T:61-->
<pre>[1999](node-main)
<pre>[1999](node-main)
rxchannel = SVXSAT/1999
rxchannel = SVXSAT/1999
startup_macro = *3403870    ; auto-connect to 403870 (transceive) on startup</pre>
startup_macro = *3403870    ; auto-connect to 403870 (transceive) on startup</pre>


<!--T:62-->
'''Belt-and-suspenders cron''' (<code>ilink 3</code> is idempotent — a no-op if already linked):
'''Belt-and-suspenders cron''' (<code>ilink 3</code> is idempotent — a no-op if already linked):


<!--T:63-->
<pre># keep node 1999 linked to 403870 every 2 minutes
<pre># keep node 1999 linked to 403870 every 2 minutes
*/2 * * * * /usr/sbin/asterisk -rx "rpt cmd 1999 ilink 3 403870" >/dev/null 2>&1</pre>
*/2 * * * * /usr/sbin/asterisk -rx "rpt cmd 1999 ilink 3 403870" >/dev/null 2>&1</pre>


== Bonus: change talkgroup from the radio (DTMF) ==
== Bonus: change talkgroup from the radio (DTMF) == <!--T:64-->


<!--T:65-->
You can move the node to another TG live — over RF with DTMF, gated by a PIN — then drop back. Handy for pushing a bulletin/net out on a different TG, then reverting.
You can move the node to another TG live — over RF with DTMF, gated by a PIN — then drop back. Handy for pushing a bulletin/net out on a different TG, then reverting.


<!--T:66-->
[[File:Chan_svx_sat_tg_control.png|center|frameless|900px|alt=DTMF dial pattern star-855 plus PIN plus action digit, with a table of actions and the control flow.]]
[[File:Chan_svx_sat_tg_control.png|center|frameless|900px|alt=DTMF dial pattern star-855 plus PIN plus action digit, with a table of actions and the control flow.]]


<!--T:67-->
'''Dial pattern:''' <code>*855</code> + '''PIN''' + action. Put the commands in <code>rpt.conf</code> under <code>[functions]</code> (PIN is the control code — a wrong PIN simply does nothing). Default PIN is <code>0000</code> — '''change it before use''':
'''Dial pattern:''' <code>*855</code> + '''PIN''' + action. Put the commands in <code>rpt.conf</code> under <code>[functions]</code> (PIN is the control code — a wrong PIN simply does nothing). Default PIN is <code>0000</code> — '''change it before use''':


<!--T:68-->
<pre>; /etc/asterisk/rpt.conf  —  base 855, PIN 0000 (CHANGE IT!)
<pre>; /etc/asterisk/rpt.conf  —  base 855, PIN 0000 (CHANGE IT!)
[functions]
[functions]
Line 231: Line 283:
85500008 = cmd,asterisk -rx "svxsat up    403872"          ; *855 0000 8 -> link up</pre>
85500008 = cmd,asterisk -rx "svxsat up    403872"          ; *855 0000 8 -> link up</pre>


<!--T:69-->
Set the default TG and an auto-revert timeout in <code>svx_sat.conf</code>:
Set the default TG and an auto-revert timeout in <code>svx_sat.conf</code>:


<!--T:70-->
<pre>[403872]
<pre>[403872]
tg        = 3149050    ; the DEFAULT TG (revert/up target)
tg        = 3149050    ; the DEFAULT TG (revert/up target)
tg_timeout = 30          ; minutes on another TG before auto-revert (0 = off)</pre>
tg_timeout = 30          ; minutes on another TG before auto-revert (0 = off)</pre>


<!--T:71-->
A temporary TG '''always''' drops back to default on a reboot, a reconnect, or after <code>tg_timeout</code> — so a forgotten switch never strands the node.
A temporary TG '''always''' drops back to default on a reboot, a reconnect, or after <code>tg_timeout</code> — so a forgotten switch never strands the node.


== Several nodes on one login ==
== Several nodes on one login == <!--T:72-->


<!--T:73-->
Give several sections the '''same''' <code>login</code> + <code>password</code> (and a <code>tg</code> each) and they multiplex onto '''one''' reflector trunk — one handshake, one heartbeat — while each still appears as its own node with its own callsign and TG. Sections with '''different''' logins open separate trunks.
Give several sections the '''same''' <code>login</code> + <code>password</code> (and a <code>tg</code> each) and they multiplex onto '''one''' reflector trunk — one handshake, one heartbeat — while each still appears as its own node with its own callsign and TG. Sections with '''different''' logins open separate trunks.


<!--T:74-->
<pre>[403872]
<pre>[403872]
host = reflector.example.org
host = reflector.example.org
Line 250: Line 307:
tg = 24016
tg = 24016


<!--T:75-->
[403873]
[403873]
host = reflector.example.org
host = reflector.example.org
Line 257: Line 315:
tg = 24021            ; different TG per node</pre>
tg = 24021            ; different TG per node</pre>


== Troubleshooting ==
== Troubleshooting == <!--T:76-->


<!--T:77-->
{| class="wikitable" style="width:100%;"
{| class="wikitable" style="width:100%;"
|-
|-
Line 280: Line 339:
|}
|}


== Reverting ==
== Reverting == <!--T:78-->


<!--T:79-->
# Restore the old <code>rxchannel</code> (uncomment it) and comment <code>rxchannel = SVXSAT/...</code>.
# Restore the old <code>rxchannel</code> (uncomment it) and comment <code>rxchannel = SVXSAT/...</code>.
# Comment <code>load = chan_svx_sat.so</code> in <code>modules.conf</code>.
# Comment <code>load = chan_svx_sat.so</code> in <code>modules.conf</code>.
# <code>sudo asterisk -rx "core restart now"</code>.
# <code>sudo asterisk -rx "core restart now"</code>.


<!--T:80-->
Remove entirely: <code>sudo apt remove asl3-chan-svx-sat</code> (add <code>--purge</code> to also drop the sample config and the <code>modules.conf</code> line).
Remove entirely: <code>sudo apt remove asl3-chan-svx-sat</code> (add <code>--purge</code> to also drop the sample config and the <code>modules.conf</code> line).


== See also ==
== See also == <!--T:81-->


<!--T:82-->
* [[Hamradio]] — all the digital-voice and gateway how-tos.
* [[Hamradio]] — all the digital-voice and gateway how-tos.
* Author / bug reports: '''SA7AUX''' &lt;bjorne@sa7aux.se&gt;. GNU GPL v2.
* Author / bug reports: '''SA7AUX''' &lt;bjorne@sa7aux.se&gt;. GNU GPL v2.

Latest revision as of 15:09, 18 October 2026

A hand-held, step-by-step guide to bridging an AllStarLink 3 node straight to a SVXReflector with chan_svx_sat — install it, get it connected, and get the audio right. No prior SvxLink knowledge needed. Copy-paste friendly.

💡 In one sentence: chan_svx_sat is an Asterisk channel driver that lets your AllStar node talk Opus directly to a SVXReflector — so you drop the old chan_usrp → svxlink hop and the extra vocoder tandem that came with it.
Before: app_rpt via USRP and svxlink to the reflector. After: app_rpt straight to the reflector over one Opus stream.
One Opus hop instead of two transcodes. Less latency, cleaner audio.

Do I even need this?

[edit | edit source]
  • You run an AllStarLink 3 node (on a Raspberry Pi or x86) and you want it on a SVXReflector talkgroup.
  • Today you probably bridge it with chan_usrp → svxlink. That works, but it transcodes the audio twice and adds a box to babysit.
  • chan_svx_sat replaces that whole hop with one driver. The audio path becomes just PCM ↔ Opus, once.

If you are not going to a SvxReflector — e.g. you only link AllStar-to-AllStar, or you use DMR/YSF — you don't need this. See Hamradio for those.

Words you'll see (plain-language glossary)

[edit | edit source]
Term What it means here
AllStarLink 3 (ASL3) The VoIP linking system built on Asterisk. Your node runs asl3-asterisk.
app_rpt The Asterisk application that is your repeater/node controller (COS, PTT, IDs, links).
SVXReflector A server that joins many SvxLink-style clients on shared talkgroups. Your node logs in to it.
Talkgroup (TG) A "channel" on the reflector. You transmit on one TG and hear whoever else is on it.
Opus The audio codec on the wire between your node and the reflector. One transcode, 8 kHz, 20 ms frames.
Trunk One TCP connection (login) to the reflector. Several nodes can share one trunk — see below.
Section A [block] in svx_sat.conf. One section = one node = one TG.

What you need before you start

[edit | edit source]
💡 Tick all four. If one is missing, fix it first — the bridge can't work without them.
  1. A working AllStarLink 3 node. Check: asterisk -V shows Asterisk 22.x+asl3-....
  2. A 64-bit OS. Debian 12 (bookworm) or 13 (trixie), on x86-64 or arm64 (Pi 3/4/5). Check: dpkg --print-architecture and . /etc/os-release; echo $VERSION_CODENAME. (The Pi Zero 2 W is intentionally not supported — heat + Wi-Fi.)
  3. A reflector login of your own — a dedicated login + auth-key, not shared with svxlink or another node. Sharing one gets the other kicked off. SvxReflector logins are upper-case callsigns.
  4. The reflector is reachable. Check: nc -vz REFLECTOR_HOST 5300.

The worked example below is a real node: AllStar node 1999 bridging to a reflector at 172.16.1.1:5300, talkgroup 24016. Swap in your own host / login / TG everywhere you see them.

How it all fits together

[edit | edit source]

Two small config files on the node, and one matching SECRET line on the reflector. That is the entire wiring:

rpt.conf points at a section in svx_sat.conf, which logs in to the reflector whose SECRET must match.
rpt.conf → a section in svx_sat.conf → a login the reflector recognises.

Step 1 — Install the package

[edit | edit source]

Pick the .deb that matches your OS and architecture:

OS / arch Package
trixie x86-64 asl3-chan-svx-sat_<ver>~trixie_amd64.deb
trixie arm64 (Pi) asl3-chan-svx-sat_<ver>~trixie_arm64.deb
bookworm x86-64 asl3-chan-svx-sat_<ver>~bookworm_amd64.deb
bookworm arm64 (Pi) asl3-chan-svx-sat_<ver>~bookworm_arm64.deb
sudo apt install ./asl3-chan-svx-sat_<ver>~<os>_<arch>.deb

Dependencies (asl3-asterisk, libopus0, libssl3) resolve automatically. The package installs the module, a sample config, this kind of documentation under /usr/share/doc/asl3-chan-svx-sat/, and adds a commented load line to modules.conf for you to enable in Step 4. Nothing loads or connects yet.

Step 2 — Create the reflector config

[edit | edit source]

Copy the sample and open it for editing:

sudo cp /etc/asterisk/svx_sat.conf.sample /etc/asterisk/svx_sat.conf
sudo chown asterisk:asterisk /etc/asterisk/svx_sat.conf
sudo chmod 640 /etc/asterisk/svx_sat.conf      # it holds your reflector password
sudoedit /etc/asterisk/svx_sat.conf

Make it look like this (name the section after the node — tidy and unambiguous):

[1999]
host     = 172.16.1.1       ; reflector hostname or IP
port     = 5300             ; reflector port (default 5300)
login    = SA7AUX-AC        ; your OWN login, UPPER-CASE, not shared
password = CHANGE_ME        ; your reflector auth-key
callsign = SA7AUX           ; name shown to the reflector
tg       = 24016            ; talkgroup to select (TX + primary RX)
💡 The login + password must match the reflector. On the reflector's [SATELLITE] section there must be a line SECRET_SA7AUX-AC=CHANGE_ME (case-sensitive). If you run the reflector too: add/change the SECRET_ line and restart the reflector — it only reads secrets at startup.

The callsign is shown as the node's name if it is free on the reflector right now; on a collision (or if left empty) it falls back to ASL-<section> (e.g. ASL-1999), re-checked automatically as names free up.

Step 3 — Point the node at it

[edit | edit source]

In /etc/asterisk/rpt.conf, in your node's stanza, comment out the old rxchannel — never delete it — and add the SVX line:

[1999](node-main)
; rxchannel = USRP/127.0.0.1:4001:4002   ; old bridge, kept so you can revert
rxchannel = SVXSAT/1999                  ; chan_svx_sat -> section [1999]
💡 Want it to survive package upgrades? Put the node stanza in /etc/asterisk/custom/rpt.conf instead — ASL3 includes that file and never overwrites it. Use the direct edit above for a quick change; use custom/ if you want your config to survive asl3-asterisk updates cleanly.

Step 4 — Enable the module

[edit | edit source]

ASL3 has autoload = no, so the module must be listed by hand. The package added a commented line — turn it on. It must live inside the [modules] section (a load line after a later section is silently ignored):

sudo sed -i 's/^; *load = chan_svx_sat.so/load = chan_svx_sat.so/' /etc/asterisk/modules.conf
grep -n '^load = chan_svx_sat.so' /etc/asterisk/modules.conf     # confirm it's active

Step 5 — Apply and verify

[edit | edit source]

An rxchannel change needs app_rpt to re-init, so restart Asterisk, then check:

sudo asterisk -rx "core restart now"
sudo asterisk -rx "svxsat show"

A healthy bridge looks like this — CONNECTED means you're done with the basic hookup:

Annotated svxsat show output explaining CONNECTED, txframes, rxframes, starts/stops, fec and plc.

Key up on the node → txframes climbs and the reflector opens the talker on your TG. When someone else talks on the TG → rxframes climbs. Done. The rest of this page is tuning and extras.

Getting the audio right

[edit | edit source]

This is where most people get stuck, so take it slow. Only the yellow stages have knobs — everything grey is automatic.

The TX and RX audio chains showing which stages are tunable (gain, AGC, jitter, tx_hold) and which are automatic (limiter, Opus FEC/PLC).

All of these live in the node's section in svx_sat.conf. After changing any of them, run sudo asterisk -rx "core restart now".

The four audio knobs

[edit | edit source]
Setting Default What it does
tx_gain 0 Preamp on TX (node → reflector), in dB. Raise if others say you're quiet; lower if they say you clip.
rx_gain 0 Preamp on RX (reflector → node), in dB. Raise if the reflector audio is too quiet on your repeater.
tx_agc / rx_agc no Automatic gain control. Turn on to even out loud/quiet stations. yes or no.
bitrate 16000 Opus bitrate in bit/s. Leave it unless you have a reason.
💡 A limiter is always on in both directions — it stops the audio clipping even if you raise the gain too far. Opus inband FEC + PLC are always on too: a lost packet is rebuilt from the next one's FEC, and an underrun is concealed instead of clicking. You don't configure any of that.

"My audio is X → do Y"

[edit | edit source]
Symptom Fix
Others say you're too quiet Raise tx_gain a few dB at a time (e.g. 3, then 6).
Others say you clip / distort Lower tx_gain a notch. The limiter guards the peak, but clean input is better.
Reflector audio too quiet on your repeater Raise rx_gain a few dB.
Loud and quiet stations are wildly uneven Turn on rx_agc = yes (and/or tx_agc = yes).
Choppy / chopped audio going out See the tx_hold fix below.
Crackle/dropouts coming in on a poor link Raise jitter (see below). FEC/PLC already help; this adds headroom.

Two more knobs: tx_hold and jitter

[edit | edit source]
Setting Default What it does
tx_hold 250 TalkerStop hold time, in ms. A brief unkey/rekey mid-over (COS flicker, link hangtime) would otherwise close and reopen the reflector talker and chop the audio. The hold keeps it open across the gap. 0 = stop immediately on unkey.
jitter 40 Jitter-buffer prefill, in ms. Higher = smoother on a poor/long link, but more latency. 0 = minimal (fine on a clean LAN). Max 500.

If audio going out is chopped: run svxsat show and watch starts/stops. One each per over is healthy. Many per over means your key is flapping — raise tx_hold (try 400).

Optional: listen to extra talkgroups

[edit | edit source]
monitor = 24020, 9990     ; extra TGs you HEAR (RX only); TX still goes to 'tg'

Keep it up — forever

[edit | edit source]

Two independent things stay up: the reflector link and the AllStar node-to-node link.

  • The reflector link is automatic. chan_svx_sat reconnects on its own (TCP + UDP heartbeats, backoff after any drop). Nothing to configure; svxsat show goes back to CONNECTED within seconds of any outage.
  • Keep the AllStar node linked to a hub? Use app_rpt's permanent connect, which re-establishes itself:
sudo asterisk -rx "rpt cmd 1999 ilink 13 403870"   # 13 = permanent, transceive

Link automatically at boot via the node stanza:

[1999](node-main)
rxchannel = SVXSAT/1999
startup_macro = *3403870     ; auto-connect to 403870 (transceive) on startup

Belt-and-suspenders cron (ilink 3 is idempotent — a no-op if already linked):

# keep node 1999 linked to 403870 every 2 minutes
*/2 * * * * /usr/sbin/asterisk -rx "rpt cmd 1999 ilink 3 403870" >/dev/null 2>&1

Bonus: change talkgroup from the radio (DTMF)

[edit | edit source]

You can move the node to another TG live — over RF with DTMF, gated by a PIN — then drop back. Handy for pushing a bulletin/net out on a different TG, then reverting.

DTMF dial pattern star-855 plus PIN plus action digit, with a table of actions and the control flow.

Dial pattern: *855 + PIN + action. Put the commands in rpt.conf under [functions] (PIN is the control code — a wrong PIN simply does nothing). Default PIN is 0000 — change it before use:

; /etc/asterisk/rpt.conf  —  base 855, PIN 0000 (CHANGE IT!)
[functions]
85500001 = cmd,asterisk -rx "svxsat settg 403872 3149060"   ; *855 0000 1 -> bulletin TG
85500002 = cmd,asterisk -rx "svxsat settg 403872 3149070"   ; *855 0000 2 -> another TG
85500000 = cmd,asterisk -rx "svxsat revert 403872"          ; *855 0000 0 -> default TG
85500009 = cmd,asterisk -rx "svxsat down   403872"          ; *855 0000 9 -> link down
85500008 = cmd,asterisk -rx "svxsat up     403872"          ; *855 0000 8 -> link up

Set the default TG and an auto-revert timeout in svx_sat.conf:

[403872]
tg         = 3149050     ; the DEFAULT TG (revert/up target)
tg_timeout = 30          ; minutes on another TG before auto-revert (0 = off)

A temporary TG always drops back to default on a reboot, a reconnect, or after tg_timeout — so a forgotten switch never strands the node.

Several nodes on one login

[edit | edit source]

Give several sections the same login + password (and a tg each) and they multiplex onto one reflector trunk — one handshake, one heartbeat — while each still appears as its own node with its own callsign and TG. Sections with different logins open separate trunks.

[403872]
host = reflector.example.org
login = SA7AUX-N      ; SAME login  -> shared trunk
password = CHANGE_ME  ; SAME secret
callsign = SA7AUX-1
tg = 24016

[403873]
host = reflector.example.org
login = SA7AUX-N      ; SAME login  -> same connection
password = CHANGE_ME
callsign = SA7AUX-2
tg = 24021            ; different TG per node

Troubleshooting

[edit | edit source]
Symptom Check
svxsat show empty / "No such command" / node has no rxchannel Is load = chan_svx_sat.so enabled inside [modules]? Did you core restart now?
down instead of CONNECTED Host/port reachable? login/password correct? Watch: sudo tail -f /var/log/asterisk/messages.log | grep -i svx
auth rejected: Invalid callsign Login must be a valid upper-case callsign, and the account must exist on the reflector.
auth rejected: Access denied Wrong password, or the login isn't registered on the reflector (SECRET_ missing / reflector not restarted).
txframes climbs but nobody hears you Is the listening client actually selecting/monitoring the same TG?
Choppy audio out, starts climbing many-per-over Key/unkey flapping → raise tx_hold (e.g. 400).
txbadsize climbing app_rpt is feeding non-slin frames — check the node's audio path.
Loads but refuses ("compile-time options") The package must match the installed asl3-asterisk version — install the deb for your exact OS.

Reverting

[edit | edit source]
  1. Restore the old rxchannel (uncomment it) and comment rxchannel = SVXSAT/....
  2. Comment load = chan_svx_sat.so in modules.conf.
  3. sudo asterisk -rx "core restart now".

Remove entirely: sudo apt remove asl3-chan-svx-sat (add --purge to also drop the sample config and the modules.conf line).

See also

[edit | edit source]
  • Hamradio — all the digital-voice and gateway how-tos.
  • Author / bug reports: SA7AUX <bjorne@sa7aux.se>. GNU GPL v2.