Le but est d’envoyer automatiquement chaque QSO validé dans WSJT-X vers un journal Wavelog, sans export ni import manuel d’un fichier ADIF.

La chaîne obtenue est la suivante :

WSJT-X -- ADIF par UDP sur le port 2333 --> WaveLogStoat -- HTTPS --> API Wavelog

Cette installation a été testée sur DigiPi le 22 juillet 2026. WaveLogStoat est lancé par systemd et peut aussi être arrêté ou redémarré depuis la page d’accueil de DigiPi.

Installation de WaveLogStoat

WaveLogStoat est un petit programme écrit en Go. Il reçoit les QSO par UDP, lit les champs ADIF puis les transmet à l’API de Wavelog.

Sur DigiPi, je l’ai compilé directement depuis les sources :

cd /home/pi
git clone https://github.com/int2001/WaveLogStoat.git
cd WaveLogStoat
go mod tidy
go build -o wavelogstoat

On peut vérifier le binaire avec :

./wavelogstoat --help

La commande doit afficher l’aide de WaveLog Stoat CLI.

Création de la configuration

Créer /home/pi/WaveLogStoat/config.ini :

[wavelog]
url = https://exemple.fr/wavelog/index.php
api_key = VOTRE_CLE_API
station_profile_id = 4
timeout = 5000

[server]
port = 2333
verbose = false

Les trois valeurs de la section [wavelog] sont à adapter :

  • url est l’adresse de l’installation Wavelog ;
  • api_key est la clé créée dans les paramètres de Wavelog ;
  • station_profile_id désigne le profil de station qui recevra les QSO.

L’identifiant du profil apparaît dans l’adresse de sa page d’édition. Par exemple :

https://exemple.fr/wavelog/index.php/station/edit/4

Dans cet exemple, l’identifiant est 4.

La clé API ne doit jamais être publiée dans un article, une capture d’écran ou une sortie de journal. J’ai aussi laissé verbose = false, car le mode détaillé affiche le contenu envoyé à l’API.

Test de l’accès à Wavelog

Avant de configurer WSJT-X, on peut tester l’URL, la clé et le profil :

cd /home/pi/WaveLogStoat
./wavelogstoat --test

Une connexion correcte donne notamment :

WaveLog connection test - Status: 201, Response: created
WaveLog connection successful

Le code HTTP 201 created confirme que Wavelog accepte la requête.

Configuration de WSJT-X

Dans File > Settings > Reporting, activer la diffusion des contacts vers N1MM Logger, puis utiliser :

Server name : 127.0.0.1
Server port : 2333

Dans le fichier /home/pi/.config/WSJT-X.ini, les valeurs correspondantes sont :

N1MMServer=127.0.0.1
N1MMServerPort=2333

Il ne faut pas utiliser ici le port UDP principal de WSJT-X, souvent configuré sur 2237. Ce port transporte les messages binaires internes de WSJT-X. WaveLogStoat attend le QSO ADIF envoyé par la fonction N1MM sur 2333.

Avec le mauvais port, WaveLogStoat reçoit bien des paquets, mais ne trouve pas le champ CALL :

Failed to parse message: missing required CALL field in ADIF

Premier essai manuel

WaveLogStoat crée son journal dans le répertoire courant. Sur mon DigiPi, /home/pi/WaveLogStoat était en lecture seule au moment de l’exécution. Je l’ai donc lancé depuis /tmp :

cd /tmp
/home/pi/WaveLogStoat/wavelogstoat -c /home/pi/WaveLogStoat/config.ini

Le démarrage correct affiche :

Starting WaveLog Stoat CLI on port 2333
UDP server listening on port 2333

Après avoir validé un QSO avec le bouton Log QSO de WSJT-X, le programme doit recevoir un enregistrement ressemblant à celui-ci :

<call:5>N4DWD <gridsquare:4>EM86 <mode:3>FT8 ... <band:3>20m ... <eor>

Puis il confirme l’envoi :

Parsed ADIF QSO: N4DWD on 14.075561 MHz
QSO successfully added: N4DWD on 14.075561 MHz

Le contact doit alors apparaître dans Wavelog.

Démarrage automatique avec systemd

Créer /etc/systemd/system/wavelogstoat.service :

[Unit]
Description=WaveLogStoat - WSJT-X to Wavelog
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=pi
WorkingDirectory=/tmp
ExecStart=/home/pi/WaveLogStoat/wavelogstoat -c /home/pi/WaveLogStoat/config.ini
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Le choix de /tmp comme répertoire de travail permet au programme d’écrire son fichier de journal malgré le système de fichiers en lecture seule de DigiPi.

Recharger systemd, activer le service au démarrage puis le lancer :

sudo systemctl daemon-reload
sudo systemctl enable --now wavelogstoat

Contrôler son état :

systemctl status wavelogstoat --no-pager

Le résultat attendu contient :

Loaded: loaded (...; enabled; ...)
Active: active (running)
UDP server listening on port 2333

Les commandes utiles par la suite sont :

sudo systemctl restart wavelogstoat
sudo systemctl stop wavelogstoat
journalctl -u wavelogstoat --no-pager

Ajout dans la page d’accueil de DigiPi

La page principale se trouve dans /var/www/html/index.php. Avant toute modification, j’en ai conservé une copie :

sudo cp /var/www/html/index.php /var/www/html/index.php.backup-20260722

J’ai d’abord ajouté le traitement du bouton avec les autres blocs $_POST :

if (isset($_POST["wavelogstoat"])) {
  $submit = $_POST["wavelogstoat"];
  if ($submit == 'on') {
      $output = shell_exec('sudo systemctl start wavelogstoat');
  }
  if ($submit == 'off') {
      $output = shell_exec('sudo systemctl stop wavelogstoat');
  }
}

Le service doit aussi être ajouté à la commande qui relève l’état de tous les services :

$output = shell_exec('sudo systemctl is-active tnc tnc300b digipeater tracker webchat node winlinkrms pat ardop wsjtx sstv fldigi js8call wavelogstoat');

Dans cette version de la page, WaveLogStoat est le quatorzième service de la liste. Son état se trouve donc à l’indice 13 :

#-- WAVELOG STOAT ------------------------------------------

echo "<tr>";
$output = $status_list[13];
if ($output == "active") {
    echo '<td bgcolor="lightgreen">';
    $checked = "checked";
} elseif ($output == "failed") {
    echo '<td bgcolor="red">';
    $checked = "";
} else {
    echo '<td bgcolor="lightgrey">';
    $checked = "";
}
echo '</td>';
echo '<td><font size=+1>WaveLog Stoat</font></td>';
echo '<td nowrap>';
echo '<form action="index.php" method="post">';
echo '<label class="switch switch-light">';
echo '<input type="hidden" name="wavelogstoat" value="off">';
echo "<input onChange='this.form.submit()' class='switch-input' type='checkbox' name='wavelogstoat' value='on' $checked />";
echo '<span class="switch-label"></span>';
echo '<span class="switch-handle"></span>';
echo '</label>';
echo '</form>';
echo '</td></tr>';

Cet indice dépend de l’ordre exact de la liste passée à systemctl is-active. Il faut donc le recalculer si la page DigiPi contient d’autres services.

J’ai enfin ajouté wavelogstoat à la commande qui efface l’état failed :

$output = shell_exec('sudo systemctl reset-failed fldigi sstv wsjtx ardop tnc300b tracker digipeater tnc node winlinkrms pat js8call wavelogstoat 2> /dev/null');

Un lien direct vers le journal peut aussi être placé dans la grille inférieure :

<a href="https://exemple.fr/wavelog/" target="wavelog" title="Ouvrir Wavelog"><strong>Wavelog</strong></a>

Avant de remplacer la page, vérifier sa syntaxe :

php -l /tmp/index.php

Si PHP répond No syntax errors detected, le fichier peut être copié :

sudo cp /tmp/index.php /var/www/html/index.php

Résultat

Dans la configuration finale :

  • WSJT-X envoie uniquement les QSO validés sur 127.0.0.1:2333 ;
  • WaveLogStoat les transmet à Wavelog par son API HTTPS ;
  • le service démarre avec DigiPi et redémarre en cas d’erreur ;
  • son état et son interrupteur apparaissent sur la page d’accueil ;
  • le mode détaillé reste désactivé pour ne pas exposer la clé API dans les journaux.

Le test final a consisté à enregistrer un QSO FT8 dans WSJT-X, puis à vérifier sa présence immédiate dans le profil de station Wavelog.

Liens