Hamradio/chan svx sat: Difference between revisions
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''' <bjorne@sa7aux.se>. GNU GPL v2. | * Author / bug reports: '''SA7AUX''' <bjorne@sa7aux.se>. 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.
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.
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_satreplaces 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]- A working AllStarLink 3 node. Check:
asterisk -VshowsAsterisk 22.x+asl3-.... - A 64-bit OS. Debian 12 (bookworm) or 13 (trixie), on x86-64 or arm64 (Pi 3/4/5). Check:
dpkg --print-architectureand. /etc/os-release; echo $VERSION_CODENAME. (The Pi Zero 2 W is intentionally not supported — heat + Wi-Fi.) - 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.
- 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 → 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)
[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]
/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:

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.

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. |
"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 showgoes back toCONNECTEDwithin 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.

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]- Restore the old
rxchannel(uncomment it) and commentrxchannel = SVXSAT/.... - Comment
load = chan_svx_sat.soinmodules.conf. 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.