Installation de svxlink sur une carte Orange Pi PC utilisant Armbian

Ludo | 22 juillet 2023

Comme pour tous les projets en cours, sur lesquels je fais face à des problèmes chronophages, j’attends le bon moment et l’éclair de génie pour avancer.
Dans le cas présent, il s’agit de faire fonctionner svxlink sur autre chose qu’une carte Raspberry Pi, devenue hors de prix suite à la pénurie de composants entraînant un énorme retard de livraisons de la part de la fondation Raspberry Pi.
En théorie, et avec de solides compétences sur les systèmes Linux, on a fini l’opération avant que le café ait le temps de refroidir (ou que la bière ait le temps de se réchauffer). En ce qui me concerne, cela fait plusieurs mois que je me suis lancé dans cette aventure et je n’ai compris que très récemment qu’une limite d’accès aux GPIO pour tout utilisateur autre que root empêchait le bon fonctionnement. Il m’aura aussi fallu résoudre diverses énigmes de paramétrage assez peu documentées. Les indications fournies à la suite dans ce billet permettent d’installer et de faire fonctionner svxlink en tant que service avec les versions disponibles au moment de la publication.

L’installation décritre ci-dessous est effectuée avec les versions suivantes:
Armbian 23.05.1 Jammy
Linux 6.1.30-sunxi
svxlink: derrnière version disponible au 22 juillet 2023

Installation du système d’exploitation

Premiers problèmes: Le peu de mises à jour des systèmes d’exploitation « officiels », la disparition progressive de leurs sources de téléchargement des paquets nécessaires à la compilation de svxlink pour ces systèmes d’exploitation, et enfin le manque de personnes utilisant svxlink avec la carte Orange Pi. Je m’intéresse particulièrement au cas de l’Orange Pi PC, mais cela reste applicable aux autres modèles de cartes Orange Pi.
Comme indiqué dans le titre de ce billet, je possède une carte Orange Pi PC, dont les systèmes d’exploitation officiellement supportés par les créateurs de cette carte sont ceux listés sur la page officielle: http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/service-and-support/Orange-Pi-PC.html

Les liens de téléchargement accessibles depuis le site Internet officiel pointent vers des fichiers datant, au mieux, de 2021. J’ai testé la version spécifique de Debian, et j’ai pu constater que les sources de téléchargement des paquets sont sur des serveurs chinois et majoritairement indisponibles.
Je me suis donc orienté vers armbian, qui ne m’a posé aucun problème dans le déroulement des étapes décrites ci-dessous, mis à part ce droit d’accès aux GPIO…

Système d’exploitation retenu: armbian

Le fichier image presque prêt à l’emploi pour la cible Orange Pi PC est disponible ici: https://www.armbian.com/orange-pi-pc/
Partant du principe que vous utilisez un PC fonctionnant avec Windows, il faudra décompresser le fichier téléchargé avec le logiciel 7-zip par exemple, disponible ici: https://7-zip.org/.
L’écriture sur la carte micro SD du fichier image portant l’extension .img, obtenu après décompression, sera effectuée en utilisant le logiciel Win32 Disk Imager, à télécharger ici: https://sourceforge.net/projects/win32diskimager/.

Une fois le fichier écrit sur la carte micro SD, il ne restera plus qu’à installer celle-ci dans le lecteur de la carte Orange Pi et à suivre les instructions au premier démarrage:

  • Définition du mot de passe de l’utilisateur root
  • Définition de l’utilisateur « standard » (si vous n’avez pas de besoin spécifique, nommez cet utilisateur svxlink)
  • Choix des paramètres de localisation: fuseau horaire, langue, etc.

Connexion à la console linux

La connexion à la console linux se fera par l’intermédiaire du logiciel putty, téléchargeable ici: https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
Pour éviter tout problème d’adresse IP, il est préférable d’utiliser une connexion par le port série du PC, vers celui de la carte Orange Pi.
La solution la plus simple consiste à utiliser une petite carte de conversion USB/UART qu’on trouve pour quelques Euros sur Aliexpress, et d’utiliser des fils type « Dupont » pour relier ce convertisseur aux broches de la carte Orange Pi:

Source: https://forum.armbian.com/topic/8237-serial-console-access-via-usb-uartgadget-mode-on-linuxwindowsosx/
Pour des raisons de fiabilité, préférez un convertisseur USB/UART utilisant un composant de la marque FTDI, et si possible compatible avec la tension des signaux de la carte Orange Pi, soit 1.8V.

Mises à jour du système

Facultatif: Désactiver l’ipv6

J’ai eu de nombreux problèmes de récupération de paquets sur des connexions utilisant des adresses ipv6.
Pour savoir si c’est activé sur votre carte réseau, il suffit de taper cette commande:
root@orangepipc:~# ip a
Vous devez obtenir une réponse de ce type:
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 02:81:78:a8:08:d9 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.59/24 brd 192.168.0.255 scope global dynamic noprefixroute eth0
valid_lft 86396sec preferred_lft 86396sec
inet6 fe80::a721:4a62:557f:82dd/64 scope link noprefixroute
valid_lft forever preferred_lft forever

On voit apparaître sur la ligne 11 ci-dessus le terme inet6, qui indique que l’ipv6 est activé sur la carte réseau filaire.

Si vous avez le même problème que moi avec l’ipv6, il faudra lister préalablement les interfaces réseau:
root@orangepipc:~# nmcli connection show
NAME               UUID                                 TYPE     DEVICE
Wired connection 1 e8a11b5b-9d4d-34e9-8aed-b08c6b6904ea ethernet eth0

Dans mon cas, l’interface réseau filaire eth0 porte le nom Wired connection 1
Pour désactiver l’ipv6, on saisit donc la commande suivante:
nmcli connection modify "Wired connection 1" ipv6.method "disabled"
Puis on redémare l’interface pour prendre en compte ce nouveau paramétrage:
nmcli connection up "Wired connection 1"

Cette action est permanente. L’ipv6 restera désactivé tant que vous n’aurez pas exécuté la commande inverse, et un redémarrage de l’interface réseau:
nmcli connection modify "Wired connection 1" ipv6.method "auto"
nmcli connection up "Wired connection 1"

Chargement des mises à jour

apt-get update
apt-get update --fix-missing
apt-get upgrade

Si vous êtes invité à valider le chargement de mises à jour, appuyez sur la touche y puis Entrée pour autoriser cette action.

Création du compte utilisateur svxlink

Si vous n’avez pas choisi ce nom d’utilisateur au premier démarrage d’armbian, saisissez la commande suivante:
sudo adduser svxlink
Dans tous les cas, ajoutez cet utilisateur au groupe daemon avec la commande suivante:
usermod -a -G daemon svxlink

Chargement des outils de compilation

Copiez/collez tout ceci sur la console linux et validez avec la touche Entrée:
apt install gcc g++ make cmake groff gzip doxygen tar git libsigc++-2.0-dev libjsoncpp-dev libcurl4-openssl-dev libpopt-dev tcl8.6-dev libgcrypt20-dev libasound2-dev libgsm1-dev libopus-dev libspeex-dev librtlsdr-dev alsa-utils
Ici aussi, il vous sera demandé de valider le chargement des fichiers:
Do you want to continue? [Y/n]
Validez en appuyant sur les touches y puis Entrée.

Chargement et installation de svxlink

Pour faire simple, copiez/collez chaque pavé de commandes ci-dessous, et validez comme expliqué précédemment à chaque fois que vous y êtes invité:
git clone https://github.com/sm0svx/svxlink.git

cd svxlink
cd src
mkdir build
cd build
cmake .. -DUSE_QT=OFF -DWITH_SYSTEMD=yes
make
make doc
make install
ldconfig

systemctl daemon-reload
systemctl enable svxlink

Édition des fichiers de configuration

rc.local

Ce fichier doit être édité pour permettre l’accès aux GPIO qui seront utilisées par svxlink:
nano /etc/rc.local
Copiez/collez les lignes suivantes, juste avant l’instruction « exit 0 » déjà présente dans ce fichier:
echo "10" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio10/direction
sleep 1
echo "7" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio7/direction
sleep 2

Vous devez obtenir ceci:
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
 
echo "10" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio10/direction
sleep 1
echo "7" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio7/direction
sleep 2
exit 0

Validez les modifications avec la combinaison de touches Ctrl+X puis appuyez sur la touche Entrée.

Redémarrez la carte pour obtenir des informations « cruciales » pour la suite des opérations, avec la commande reboot:
root@orangepipc:~# reboot

Droits d’accès aux GPIO

C’est ce qui m’a posé le plus de problèmes, car j’ai mis beaucoup de temps à comprendre que l’exécution automatique de svxlink.service au démarrage de l’Orange Pi PC venait d’un problème de privilèges de l’utilisateur svxlink.
Avant de créer un groupe nommé gpio et de définir les droits de l’utilisateur svxlink, il faut vérifier les liens symboliques qui se cachent derrière les accès système aux GPIO:
root@orangepipc:~# ls -l /sys/class/gpio
total 0
--w------- 1 root root 4096 Jul 30 12:47 export
lrwxrwxrwx 1 root root 0 Jul 30 12:47 gpio10 -> ../../devices/platform/soc/1c20800.pinctrl/gpiochip0/gpio/gpio10
lrwxrwxrwx 1 root root 0 Jul 30 12:47 gpio7 -> ../../devices/platform/soc/1c20800.pinctrl/gpiochip0/gpio/gpio7
lrwxrwxrwx 1 root root 0 Jul 30 12:47 gpiochip0 -> ../../devices/platform/soc/1c20800.pinctrl/gpio/gpiochip0
lrwxrwxrwx 1 root root 0 Jul 30 12:47 gpiochip352 -> ../../devices/platform/soc/1f02c00.pinctrl/gpio/gpiochip352
--w------- 1 root root 4096 Jul 30 12:47 unexport

On voit ici que le système va accéder en réalité aux fichiers contenus dans /sys/devices/platform/soc/1c20800.pinctrl.
Donc, après vous être identifiés avec le compte utilisateur root, il faudra saisir les commandes suivantes:
groupadd -g 997 gpio
chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio
chown -R root:gpio /sys/devices/platform/soc/1c20800.pinctrl && chmod -R 770 /sys/devices/platform/soc/1c20800.pinctrl
adduser svxlink gpio
usermod -aG gpio svxlink

Vous devez obtenir ceci:
root@orangepipc:~# sudo groupadd -g 997 gpio
root@orangepipc:~# chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio
root@orangepipc:~# chown -R root:gpio /sys/devices/platform/soc/1c20800.pinctrl && chmod -R 770 /sys/devices/platform/soc/1c20800.pinctrl
root@orangepipc:~# sudo adduser svxlink gpio
Adding user `svxlink' to group `gpio' ...
Adding user svxlink to group gpio
Done.
root@orangepipc:~# usermod -aG gpio svxlink

Comme tout n’est pas conservé à chaque redémarrage, on va ajouter ce qui nous intéresse dans /etc/rc.local.
Ce qui suit n’est pas forcément très élégant, mais permet d’aboutir à nos fins:
nano /etc/rc.local
Copiez/collez les lignes suivantes, juste avant l’instruction « exit 0 » déjà présente dans ce fichier:
sudo su -
chown -R root:gpio /sys/devices/platform/soc/1c20800.pinctrl && chmod -R 770 /sys/devices/platform/soc/1c20800.pinctrl

Vous devez obtenir ceci:
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
 
echo "10" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio10/direction
sleep 1
echo "7" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio7/direction
sleep 2
 
sudo su -
chown -R root:gpio /sys/devices/platform/soc/1c20800.pinctrl && chmod -R 770 /sys/devices/platform/soc/1c20800.pinctrl
 
exit 0

Validez les modifications avec la combinaison de touches Ctrl+X puis appuyez sur la touche Entrée.

Variables d’exécution du service svxlink

nano /usr/local/etc/default/svxlink
Modifiez si besoin les chemins d’accès pour obtenir ceci:
#############################################################################
#
# Configuration file for the SvxLink Systemd unit file
#
#############################################################################
 
# The user to run the SvxLink server as
RUNASUSER=svxlink
 
# Specify which configuration file to use
CFGFILE=/usr/local/etc/svxlink/svxlink.conf
 
# Where to place the log file
LOGFILE=/var/log/svxlink
 
# Where to place the PID file
PIDFILE=/run/svxlink.pid
 
# Disable Alsa zerofill if set to 0 (see manual page)
#ASYNC_AUDIO_ALSA_ZEROFILL=1
 
# Enable UDP zerofill if set to 1 (see manual page)
#ASYNC_AUDIO_UDP_ZEROFILL=0

Validez les modifications avec la combinaison de touches Ctrl+X puis appuyez sur la touche Entrée.

Fichier d’exécution de svxlink en tant que service, via systemd

nano /usr/lib/systemd/system/svxlink.service

Normalement, tout est déjà correct dans ce fichier. On va simplement indiquer que l’exécution des commandes doit se faire en tant qu’utilisateur root, et aussi ajoutrer un délai de rééxécution du service en cas d’échec (principalement lors du démarrage de la carte Orange Pi PC car les privilècges d’accès aux GPIO sont définis après la première exécution du servicve)

Pour ce faire, on va ajouter l’indication User=root juste en dessous de la balise [Service]:
[Service]
User=root

Et on va ajouter le délai de redémarrage du service en cas d’erreur RestartSec=20s juste après l’insttrction Restart=on-failure:
Restart=on-failure
RestartSec=20s

Au final, vous devez obtenir ceci:
# This file is part of SvxLink -- a voice services system for ham radio
#
# Copyright (C) 2003-2019 Tobias Blomberg / SM0SVX
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
[Unit]
Description=SvxLink repeater control software
Documentation=man:svxlink(1)
Requires=svxlink_gpio_setup.service
After=network.target remote-fs.target syslog.target time.target
After=svxlink_gpio_setup.service
 
[Service]
User=root
EnvironmentFile=/usr/local/etc/default/svxlink
PIDFile=${PIDFILE}
ExecStartPre=-/bin/touch ${LOGFILE}
ExecStartPre=-/bin/chown ${RUNASUSER} ${LOGFILE}
ExecStart=/usr/local/bin/svxlink --logfile=${LOGFILE} --config=${CFGFILE} --pid>
ExecReload=/bin/kill -s HUP $MAINPID
Restart=on-failure
RestartSec=20s
TimeoutStartSec=60
TimeoutStopSec=10
#WatchdogSec=
#NotifyAccess=main
LimitCORE=infinity
WorkingDirectory=/usr/local/etc/svxlink
 
[Install]
WantedBy=multi-user.target

Validez les modifications avec la combinaison de touches Ctrl+X puis appuyez sur la touche Entrée.

svxlink.conf

nano /usr/local/etc/svxlink/svxlink.conf

Définissez ici tout ce qui est propre à votre relais, ainsi que l’interface audio et GPIO.
Là, il y a trop de possibilités pour pouvoir fournir un fichier type prêt à l’emploi. Je vous fournis ma config telle qu’elle (à part l’indicatif du relais 😉 )

Quelques précisions tout de même concernant l’interface audio:
Le nom de l’interface est alsa:plughw:x, avec x valant 0, ou 1, ou 2, etc. selon votre configuration matérielle.
Afin de savoir quel chiffre définir pour les deux paramètres AUDIO_DEV présents respectivement dans le bloc [Rx1] et [Tx1], il suffit d’ouvrir alsamixer:
root@orangepipc:~# alsamixer

Puis d’appuyer sur la touche F6 afin de lister les cartes son disponibles:

Ici on voit que ma carte son USB est le périphérique 1, donc il faudra définir ce chiffre deux fois: AUDIO_DEV=alsa:plughw:1.


###############################################################################
# #
# Configuration file for the SvxLink server #
# #
###############################################################################
 
[GLOBAL]
#MODULE_PATH=/usr/local/lib/svxlink
LOGIC_CORE_PATH=/usr/local/lib/svxlink
LOGICS=RepeaterLogic
CFG_DIR=svxlink.d
TIMESTAMP_FORMAT="%c"
CARD_SAMPLE_RATE=48000
#CARD_CHANNELS=1
#LOCATION_INFO=LocationInfo
#LINKS=LinkToR4
 
[SimplexLogic]
TYPE=Simplex
RX=Rx1
TX=Tx1
MODULES=ModuleHelp,ModuleParrot,ModuleTclVoiceMail
CALLSIGN=MYCALL
SHORT_IDENT_INTERVAL=60
LONG_IDENT_INTERVAL=60
#IDENT_ONLY_AFTER_TX=4
#EXEC_CMD_ON_SQL_CLOSE=500
EVENT_HANDLER=/usr/local/share/svxlink/events.tcl
DEFAULT_LANG=fr_FR
RGR_SOUND_DELAY=0
#RGR_SOUND_ALWAYS=0
REPORT_CTCSS=123
#TX_CTCSS=ALWAYS
MACROS=Macros
FX_GAIN_NORMAL=0
FX_GAIN_LOW=-12
#ACTIVATE_MODULE_ON_LONG_CMD=4:EchoLink
#QSO_RECORDER=8:QsoRecorder
#ONLINE_CMD=998877
#ONLINE=1
#MUTE_RX_ON_TX=1
#MUTE_TX_ON_RX=1
#STATE_PTY=/var/run/svxlink/state
#DTMF_CTRL_PTY=/dev/shm/simplex_dtmf_ctrl
#CTCSS_TO_TG=77.0:999,123.0:9990,146.2:9992
#CTCSS_TO_TG_DELAY=1000
 
[RepeaterLogic]
TYPE=Repeater
RX=Rx1
TX=Tx1
MODULES=ModuleHelp,ModuleParrot,ModuleTclVoiceMail
CALLSIGN=MYCALL
SHORT_IDENT_INTERVAL=10
LONG_IDENT_INTERVAL=60
#IDENT_ONLY_AFTER_TX=4
#EXEC_CMD_ON_SQL_CLOSE=500
EVENT_HANDLER=/usr/local/share/svxlink/events.tcl
DEFAULT_LANG=fr_FR
RGR_SOUND_DELAY=0
REPORT_CTCSS=123
#TX_CTCSS=SQL_OPEN
MACROS=Macros
#SEL5_MACRO_RANGE=03400,03499
FX_GAIN_NORMAL=0
FX_GAIN_LOW=-12
#QSO_RECORDER=8:QsoRecorder
#NO_REPEAT=1
IDLE_TIMEOUT=30
OPEN_ON_1750=1000
#OPEN_ON_CTCSS=1000
#OPEN_ON_DTMF=*
#OPEN_ON_SQL=5000
#OPEN_ON_SEL5=01234
#OPEN_SQL_FLANK=OPEN
#OPEN_ON_SQL_AFTER_RPT_CLOSE=10
IDLE_SOUND_INTERVAL=3000
#SQL_FLAP_SUP_MIN_TIME=1000
#SQL_FLAP_SUP_MAX_COUNT=10
#ACTIVATE_MODULE_ON_LONG_CMD=4:EchoLink
#IDENT_NAG_TIMEOUT=15
#IDENT_NAG_MIN_TIME=2000
#ONLINE_CMD=998877
#ONLINE=1
#STATE_PTY=/var/run/svxlink/state
#DTMF_CTRL_PTY=/dev/shm/repeater_dtmf_ctrl
#CTCSS_TO_TG=77.0:999,123.0:9990,146.2:9992
#CTCSS_TO_TG_DELAY=0
 
[ReflectorLogic]
TYPE=Reflector
#DNS_DOMAIN=example.com
HOSTS=reflector-primary.example.org,reflector-secondary.example.org:5301
#HOST_PORT=5300
#HOST_PRIO=100
#HOST_PRIO_INC=1
#HOST_WEIGHT=10
CALLSIGN="MYCALL"
AUTH_KEY="Change this key now!"
#JITTER_BUFFER_DELAY=0
#DEFAULT_TG=999
#MONITOR_TGS=99901,99902,99903
#TG_SELECT_TIMEOUT=30
ANNOUNCE_REMOTE_MIN_INTERVAL=300
EVENT_HANDLER=/usr/local/share/svxlink/events.tcl
#NODE_INFO_FILE=/usr/local/etc/svxlink/node_info.json
#MUTE_FIRST_TX_LOC=1
#MUTE_FIRST_TX_REM=1
#TMP_MONITOR_TIMEOUT=3600
#UDP_HEARTBEAT_INTERVAL=15
QSY_PENDING_TIMEOUT=15
#DEFAULT_LANG=fr_FR
#VERBOSE=1
 
[LinkToR4]
CONNECT_LOGICS=RepeaterLogic:94:SK3AB,SimplexLogic:92:SK3CD
#DEFAULT_ACTIVE=1
TIMEOUT=300
#ACTIVATE_ON_ACTIVITY=RepeaterLogic
 
[Macros]
1=EchoLink:9999#
9=Parrot:0123456789#
03400=EchoLink:9999#
 
[QsoRecorder]
REC_DIR=/usr/local/var/spool/svxlink/qso_recorder
#MIN_TIME=1000
MAX_TIME=3600
SOFT_TIME=300
MAX_DIRSIZE=1024
#DEFAULT_ACTIVE=1
#TIMEOUT=300
#QSO_TIMEOUT=300
#ENCODER_CMD=/usr/bin/oggenc -Q \"%f\" && rm \"%f\"
 
[Voter]
TYPE=Voter
RECEIVERS=Rx1,Rx2,Rx3
VOTING_DELAY=200
BUFFER_LENGTH=0
#REVOTE_INTERVAL=1000
#HYSTERESIS=50
#SQL_CLOSE_REVOTE_DELAY=500
#RX_SWITCH_DELAY=500
#COMMAND_PTY=/dev/shm/voter_ctrl
#VERBOSE=1
 
[MultiTx]
TYPE=Multi
TRANSMITTERS=Tx1,Tx2,Tx3
 
[NetRx]
TYPE=Net
HOST=remote.rx.host
TCP_PORT=5210
#LOG_DISCONNECTS_ONCE=0
AUTH_KEY="Change this key now!"
CODEC=S16
#SPEEX_ENC_FRAMES_PER_PACKET=4
#SPEEX_ENC_QUALITY=4
#SPEEX_ENC_BITRATE=15000
#SPEEX_ENC_COMPLEXITY=2
#SPEEX_ENC_VBR=0
#SPEEX_ENC_VBR_QUALITY=4
#SPEEX_ENC_ABR=15000
#SPEEX_DEC_ENHANCER=1
#OPUS_ENC_FRAME_SIZE=20
#OPUS_ENC_COMPLEXITY=10
#OPUS_ENC_BITRATE=20000
#OPUS_ENC_VBR=1
 
[NetTx]
TYPE=Net
#TX_ID=T
HOST=remote.tx.host
TCP_PORT=5210
#LOG_DISCONNECTS_ONCE=0
AUTH_KEY="Change this key now!"
CODEC=S16
#SPEEX_ENC_FRAMES_PER_PACKET=4
#SPEEX_ENC_QUALITY=4
#SPEEX_ENC_BITRATE=15000
#SPEEX_ENC_COMPLEXITY=2
#SPEEX_ENC_VBR=0
#SPEEX_ENC_VBR_QUALITY=4
#SPEEX_ENC_ABR=15000
#SPEEX_DEC_ENHANCER=1
#OPUS_ENC_FRAME_SIZE=20
#OPUS_ENC_COMPLEXITY=10
#OPUS_ENC_BITRATE=20000
#OPUS_ENC_VBR=1
 
[Rx1]
TYPE=Local
#RX_ID=?
AUDIO_DEV=alsa:plughw:1
AUDIO_CHANNEL=0
#AUDIO_DEV_KEEP_OPEN=0
LIMITER_THRESH=-6
SQL_DET=GPIO
SQL_START_DELAY=0
SQL_DELAY=0
SQL_HANGTIME=2000
#SQL_EXTENDED_HANGTIME=1000
#SQL_EXTENDED_HANGTIME_THRESH=15
#SQL_TIMEOUT=600
VOX_FILTER_DEPTH=20
VOX_THRESH=1000
#CTCSS_MODE=2
CTCSS_FQ=123
#CTCSS_SNR_OFFSET=0
#CTCSS_SNR_OFFSETS=88.5:-1.0,136.5:-0.5
#CTCSS_OPEN_THRESH=15
#CTCSS_CLOSE_THRESH=9
#CTCSS_BPF_LOW=60
#CTCSS_BPF_HIGH=270
#CTCSS_EMIT_TONE_DETECTED=0
SERIAL_PORT=/dev/ttyS0
SERIAL_PIN=CTS
#SERIAL_SET_PINS=DTR!RTS
#EVDEV_DEVNAME=/dev/input/by-id/usb-SYNIC_SYNIC_Wireless_Audio-event-if03
#EVDEV_OPEN=1,163,1
#EVDEV_CLOSE=1,163,0
GPIO_PATH=/sys/class/gpio
GPIO_SQL_PIN=gpio10
#SQL_GPIOD_CHIP=gpiochip0
#SQL_GPIOD_LINE=22
#SQL_GPIOD_BIAS=PULLDOWN
#PTY_PATH=/tmp/rx1_sql
#HID_DEVICE=/dev/hidraw3
#HID_SQL_PIN=VOL_UP
#SIGLEV_DET=TONE
SIGLEV_SLOPE=1
SIGLEV_OFFSET=0
#SIGLEV_BOGUS_THRESH=120
#TONE_SIGLEV_MAP=100,84,60,50,37,32,28,23,19,8
SQL_SIGLEV_OPEN_THRESH=30
SQL_SIGLEV_CLOSE_THRESH=10
DEEMPHASIS=0
#SQL_TAIL_ELIM=300
#PREAMP=6
PEAK_METER=1
DTMF_DEC_TYPE=INTERNAL
DTMF_MUTING=1
DTMF_HANGTIME=40
DTMF_SERIAL=/dev/ttyS0
#DTMF_PTY=/tmp/rx1_dtmf
#DTMF_MAX_FWD_TWIST=8
#DTMF_MAX_REV_TWIST=4
#1750_MUTING=1
#SEL5_DEC_TYPE=INTERNAL
#SEL5_TYPE=ZVEI1
#FQ=433475000
#MODULATION=FM
#WBRX=WbRx1
#OB_AFSK_ENABLE=0
#OB_AFSK_VOICE_GAIN=6
#IB_AFSK_ENABLE=0
 
[WbRx1]
#TYPE=RtlUsb
#DEV_MATCH=0
#HOST=localhost
#PORT=1234
#CENTER_FQ=435075000
#FQ_CORR=0
#GAIN=0
#PEAK_METER=1
#SAMPLE_RATE=960000
 
[Tx1]
TYPE=Local
TX_ID=T
AUDIO_DEV=alsa:plughw:1
AUDIO_CHANNEL=0
#AUDIO_DEV_KEEP_OPEN=0
LIMITER_THRESH=-6
PTT_TYPE=GPIO
PTT_PORT=/dev/ttyS0
PTT_PIN=gpio7
#HID_DEVICE=/dev/hidraw3
#HID_PTT_PIN=GPIO3
#SERIAL_SET_PINS=DTR!RTS
GPIO_PATH=/sys/class/gpio
#PTT_GPIOD_CHIP=gpiochip0
#PTT_GPIOD_LINE=17
#PTT_HANGTIME=1000
#TIMEOUT=300
TX_DELAY=500
#CTCSS_FQ=136.5
#CTCSS_LEVEL=-24
PREEMPHASIS=0
DTMF_TONE_LENGTH=100
DTMF_TONE_SPACING=50
DTMF_DIGIT_PWR=-15
#MASTER_GAIN=0.0
#OB_AFSK_ENABLE=0
#OB_AFSK_VOICE_GAIN=-6
#OB_AFSK_LEVEL=-12
#OB_AFSK_TX_DELAY=100
#IB_AFSK_ENABLE=0
#IB_AFSK_LEVEL=-6
#IB_AFSK_TX_DELAY=100
 
[LocationInfo]
APRS_SERVER_LIST=euro.aprs2.net:14580
#STATUS_SERVER_LIST=aprs.echolink.org:5199
#LON_POSITION=12.10.00E
#LAT_POSITION=51.10.00N
#CALLSIGN=EL-DL0ABC
#FREQUENCY=438.875
#TX_POWER=8
#ANTENNA_GAIN=6
#ANTENNA_HEIGHT=20m
#ANTENNA_DIR=-1
PATH=WIDE1-1
BEACON_INTERVAL=10
#TONE=136
COMMENT=SvxLink by SM0SVX (www.svxlink.org)

Forçage de l’index de la carte son USB

Afin d’éviter une attribution d’index différente, selon l’ordre de détection des interfaces à l’initialisation du système d’exploitation, nous allons la figer. Cela évitera une erreur bloquante à l’exécution de svxlink, qui ne pourra pas utiliser la carte son définie pour l’interface audio du relais.
Vu qu’on utilise armbian, comme la version de spotnik mentionnée dans cet autre billet, on va appliquer la même procédure.
Ouvrez le ficher de configuration d’alsa:
nano /etc/modprobe.d/alsa.conf
Copier/coller les lignes suivantes dans le fichier:
# copy to /etc/modprobe.d/
#
# It is force set the number 0 for index alsa loop
options snd-aloop index=0
options snd-usb-audio index=1

Dans la ligne 5 ci-dessus, j’ai figé l’index de ma carte son USB à 1.

Validez les modifications avec la combinaison de touches Ctrl+X puis appuyez sur la touche Entrée.

Essai en exécutant manuellement svxlink

Taper simplement svxlink puis valider avec Entrée:
root@orangepipc:~# svxlink
SvxLink v1.7.99.86 Copyright (C) 2003-2023 Tobias Blomberg / SM0SVX
 
SvxLink comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
welcome to redistribute it in accordance with the terms and conditions in the
GNU GPL (General Public License) version 2 or later.
 
Using configuration file: /usr/local/etc/svxlink/svxlink.conf
--- Using sample rate 48000Hz
 
Starting logic: RepeaterLogic
Found plugin: /usr/local/lib/svxlink/RepeaterLogic.so
RepeaterLogic: Loading RX "Rx1"
RepeaterLogic: Loading TX "Tx1"
RepeaterLogic: Loading module "ModuleHelp"
Found /usr/local/lib/svxlink/ModuleHelp.so
Module Help v1.0.0 starting...
RepeaterLogic: Loading module "ModuleParrot"
Found /usr/local/lib/svxlink/ModuleParrot.so
Module Parrot v1.1.1 starting...
RepeaterLogic: Loading module "ModuleTclVoiceMail"
Found /usr/local/lib/svxlink/ModuleTcl.so
Module Tcl v1.0.1 starting...
RepeaterLogic: Event handler script successfully loaded.

Quittez avec la combinaison de touches Ctrl+C.

Si vous avez un problème de paramétrage de la carte son USB, vous verrez les messages suivants apparaître à la place:
root@orangepipc:~# svxlink
SvxLink v1.7.99.81 Copyright (C) 2003-2023 Tobias Blomberg / SM0SVX
 
SvxLink comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
welcome to redistribute it in accordance with the terms and conditions in the
GNU GPL (General Public License) version 2 or later.
 
Using configuration file: /etc/svxlink/svxlink.conf
--- Using sample rate 48000Hz
 
Starting logic: RepeaterLogic
Found plugin: /usr/lib/arm-linux-gnueabihf/svxlink/RepeaterLogic.so
RepeaterLogic: Loading RX "Rx1"
*** ERROR: Open capture audio device failed: No such file or directory
*** ERROR: Could not open audio device for receiver "Rx1"
*** ERROR: Could not initialize RX "Rx1"
*** ERROR: Could not load or initialize Logic object "RepeaterLogic". Skipping...
*** ERROR: No logics available. Bailing out...

Le cas échéant, éditez à nouveau svxlink.conf et modifiez le chemin vers l’entrée et la sortie de la carte son:
AUDIO_DEV=alsa:plughw:1

Exécution automatique de svxlink

Maintenant que tout est paramétré, vous pouvez redémarrer la carte avec la commande reboot:
root@orangepipc:~# reboot

À chaque démarrage, svxlink sera exécuté automatiquement grace à svxlink.service.
On peut valider son bon fonctionnement en utilisant la commande systemctl status svxlink.service:
root@orangepipc:~# systemctl status svxlink.service
● svxlink.service - SvxLink repeater control software
Loaded: loaded (/lib/systemd/system/svxlink.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2023-07-30 13:19:13 CEST; 4min 37s ago
Docs: man:svxlink(1)
Process: 1351 ExecStartPre=/bin/touch ${LOGFILE} (code=exited, status=0/SUCCESS)
Process: 1352 ExecStartPre=/bin/chown ${RUNASUSER} ${LOGFILE} (code=exited, status=0/SUCCESS)
Main PID: 1353 (svxlink)
Tasks: 1 (limit: 2044)
Memory: 5.1M
CPU: 2.063s
CGroup: /system.slice/svxlink.service
└─1353 /usr/local/bin/svxlink --logfile=/var/log/svxlink --config=/usr/local/etc/svxlink/svxlink.conf --pidfile=/run/svxlink.pid --runasuser=svxlink
 
Jul 30 13:19:13 orangepipc systemd[1]: Starting SvxLink repeater control software...
Jul 30 13:19:13 orangepipc systemd[1]: Started SvxLink repeater control software.

Installation des fichiers audio pour les annonces automatiques

Le répertoire où se trouvent les sons est hérité de celui défini dans svxlink.conf, plus précisément dans la variable EVENT_HANDLER=.
En prenant comme référence mon fichier svxlink.conf, la base du chemin vers ces fichiers de sons est: /usr/local/share/svxlink/sounds

Si on consulte le paramétrage du fichier events.tcl défini dans la variable EVENT_HANDLER= (donc /usr/local/share/svxlink/events.tcl); on voit ceci:
proc playMsg {context msg {warn 1}} {
global basedir
global langdir
 
set candidates [glob -nocomplain \
"$langdir/local/$context/$msg.{wav,raw,gsm}" \
"$basedir/sounds/local/$context/$msg.{wav,raw,gsm}" \
"$basedir/sounds/$context/$msg.{wav,raw,gsm}" \
"$langdir/local/Default/$msg.{wav,raw,gsm}" \
"$basedir/sounds/local/Default/$msg.{wav,raw,gsm}" \
"$langdir/Default/$msg.{wav,raw,gsm}"];
if {[llength $candidates] > 0} {
playFile [lindex $candidates 0];
} else {
if {$warn} {
puts "*** WARNING: Could not find audio clip \"$msg\" in context \"$context\"";
}
return 0
}
return 1
}

À chaque annonce utilisant les fichiers audio, c’est dans un de ces emplacements que svxlink va chercher les fichiers sonores pré-enregistrés.
On va profiter du paramétrage déjà défini en ligne 8 ci-dessus, pour créer le répertoire où seront stockés nos fichiers audio et y déposer ces fichiers.

Copie des fichiers audio

Pour commencer, on va créer le sous-répertoire nommé fr_FR, dans le répertoire sounds qui sera utilisé par svxlink:
mkdir /usr/local/share/svxlink/sounds/fr_FR

Assurez vous de bien avoir défini DEFAULT_LANG=fr_FR dans svxlink.conf !

On se rend ensuite dans ce répertoire pour y charger un ensemble de fichiers audio prêts à l’emploi:
cd /usr/local/share/svxlink/sounds/fr_FR

Puis on télécharge le fichier zip:
wget http://f8asb.free.fr/blog/fr_FR_Agnes.zip

On décompresse le fichier zip:
unzip fr_FR_Agnes.zip

On déplace les fichiers au bon endroit:
mv /usr/local/share/svxlink/sounds/fr_FR/fr_FR_Agnes/* /usr/local/share/svxlink/sounds/fr_FR

Et on supprime enfin tout ce qui n’est plus nécessaire:
rm fr_FR_Agnes.zip
rmdir -v --ignore-fail-on-non-empty -p fr_FR_Agnes

Il vous reviendra ensuite de faire les ajustements souhaités pour obtenir les annonces vocales personnalisées de votre relais, dans le fichier events.tcl mentionné précédemment, et en prenant le soin de générer et enregistrer au bon endroit les fichiers audio correspondants.

À savoir

Pour le déboggage, vous pouvez vous aider entre autre des logs stopckés dans le fichier /var/log/svxlink, avec la commande suivante par exemple:
tail -n 40 -f /var/log/svxlink

L’argument -n 40 permet d’afficher uniquement les 40 dernières lignes du journal d’événements.

Exemple de défaut d’encodage d’un fichier wav, indiqué dans ce journal d’événements:
*** WARNING: Illegal WAV file header. ChunkID is not "RIFF": /usr/local/share/svxlink/sounds/en_US/Default/phonetic_f.wav

Reste à faire

  • Décrire la procédure de calibration audio, avec devcal ;
  • Ajouter un timer qui va relancer le svxlink.service en cas de plantage.

Ces étapes serot décrites ultérieurement, quand j’aurais un peu de temps libre.

Sources

Mes compétences étant relativement limitées concernant Linux, Armbian, et svxlink, je me suis largement appuyé sur les sites suivants pour rédiger ce billet:
https://jeff9v1as.files.wordpress.com/2015/04/how-to-install-svxlink-on-raspberry-pi.pdf
https://drc.bz/technik/analog-digitaltechnik/svxlink-mit-orange-pi-zero/
https://f6kex.fr/index.php/author/adminrcpa/
https://f5nlg.wordpress.com/category/configuration-du-link/
https://forum.armbian.com/topic/1886-gpio-access-from-user-space/
http://svxcard.f5uii.net/doku.php?id=fr:fichiers_audio_16k
http://www.f1tzo.com/installation-de-svxlink-chap-4/

Chaque site m’a permis d’avancer dans cette aventure, mais sans fournir l’intégralité des informations recherchées. Ma configuration matérielle et logicielle est visiblement spécifique, ou le contenu de ces sites est partiellement obsolète. Si vous voulez éviter qu’il en soit de même pour tout ce qui est décrit ici, vous pouvez me faire part de vos remarques en utilisant le forulaire de commentaires ci-dessous.

Leave a Reply


La période de vérification reCAPTCHA a expiré. Veuillez recharger la page.