dir refactor
This commit is contained in:
+58
-93
@@ -1,12 +1,13 @@
|
||||
# Role: scanner_digirig
|
||||
# Configure direwolf with the Digirig device
|
||||
# CONFIGURE ARGUS AX.25 VHF STACK!
|
||||
# This uses a dedicated 2 meter radio with a dedicated antenna, a Digirig and software like
|
||||
# Direwolf, Socat and the Linux kernel AX.25 implementation.
|
||||
#
|
||||
# - Set up udev rules to make special device drivers for the Digirig in /dev/radio so we don't
|
||||
# have to relay on /dev/ttyUSB0, 1 or whatever number the OS happens to assign. This gives the
|
||||
# device names consistency.
|
||||
# device names consistency. ALso name the ALSA sound device "digirig".
|
||||
#
|
||||
# - Set up systemd service to start Direwolf when the device is connected via USB, and to stop it
|
||||
# when the radio is disconnected.
|
||||
# - Set up systemd service to start the AX.25 stack when the device is connected via USB, and to
|
||||
# stop it when the radio is disconnected.
|
||||
#
|
||||
# - Copy configuration files
|
||||
#
|
||||
@@ -15,17 +16,18 @@
|
||||
file:
|
||||
path: "{{item}}"
|
||||
state: directory
|
||||
owner: busnet
|
||||
group: busnet
|
||||
owner: argus
|
||||
group: argus
|
||||
mode: u=rwx,g=rwx,o=rx
|
||||
with_items:
|
||||
- /opt/busnet/direwolf
|
||||
- /opt/busnet/direwolf/config
|
||||
- /opt/busnet/direwolf/logs
|
||||
- /opt/argus/scripts
|
||||
- /opt/argus/direwolf
|
||||
- /opt/argus/direwolf/config
|
||||
- /opt/argus/direwolf/logs
|
||||
|
||||
- name: Make sure busnet user is in groups for audio and USB access
|
||||
- name: Make sure argus user is in groups for audio and USB access
|
||||
ansible.builtin.user:
|
||||
name: busnet
|
||||
name: argus
|
||||
groups: "{{item}}"
|
||||
append: yes
|
||||
with_items:
|
||||
@@ -34,10 +36,10 @@
|
||||
- audio
|
||||
- plugdev
|
||||
|
||||
- name: Grant full passwordless sudo access to busnet user
|
||||
- name: Grant full passwordless sudo access to argus user
|
||||
ansible.builtin.copy:
|
||||
content: "busnet ALL=(ALL) NOPASSWD:ALL"
|
||||
dest: /etc/sudoers.d/busnet
|
||||
content: "argus ALL=(ALL) NOPASSWD:ALL"
|
||||
dest: /etc/sudoers.d/argus
|
||||
mode: '0440'
|
||||
owner: root
|
||||
group: root
|
||||
@@ -50,108 +52,45 @@
|
||||
- ax25-apps
|
||||
- libax25
|
||||
state: present
|
||||
|
||||
- name: Ensure AX.25 and NET/ROM kernel modules are loaded
|
||||
community.general.modprobe:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
with_items:
|
||||
- ax25
|
||||
- netrom
|
||||
|
||||
###################################################################################################
|
||||
# Direwolf bash script and config
|
||||
# AX25 VHF bash script
|
||||
###################################################################################################
|
||||
|
||||
- name: Copy digirig-direwolf.sh AX.25 stack script
|
||||
- name: Copy ax25-vhf.sh script
|
||||
copy:
|
||||
src: "templates/digirig-direwolf.sh"
|
||||
dest: "/opt/busnet/direwolf/digirig-direwolf.sh"
|
||||
owner: busnet
|
||||
group: busnet
|
||||
src: "templates/ax25-vhf.sh"
|
||||
dest: "/opt/argus/scripts/ax25-vhf.sh"
|
||||
owner: argus
|
||||
group: argus
|
||||
mode: "0755"
|
||||
|
||||
- name: Copy Direwolf config for Digirig
|
||||
template:
|
||||
src: "templates/digirig-direwolf.conf.j2"
|
||||
dest: "/opt/busnet/direwolf/config/digirig.conf"
|
||||
owner: busnet
|
||||
group: busnet
|
||||
dest: "/opt/argus/direwolf/config/digirig.conf"
|
||||
owner: argus
|
||||
group: argus
|
||||
|
||||
###################################################################################################
|
||||
# SYSTEMD: Direwolf
|
||||
# SYSTEMD: Install argus-ax25-vhf.service
|
||||
###################################################################################################
|
||||
|
||||
- name: Copy AX.25 bash script to start direwolf and utils
|
||||
template:
|
||||
src: "templates/digirig-direwolf.conf.j2"
|
||||
dest: "/opt/busnet/direwolf/config/digirig.conf"
|
||||
owner: busnet
|
||||
group: busnet
|
||||
|
||||
# udev rules start this automatically when the radio USB is connected, and stop when disconnected.
|
||||
- name: Install systemd unit file for Direwolf/AX.25 stack
|
||||
- name: Install systemd unit file for AX.25 VHF stack
|
||||
template:
|
||||
src: "templates/digirig-direwolf.service.j2"
|
||||
dest: "/etc/systemd/system/digirig-direwolf.service"
|
||||
src: "templates/argus-ax25-vhf.service.j2"
|
||||
dest: "/etc/systemd/system/argus-ax25-vhf.service"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Enable digirig-direwolf service
|
||||
- name: Enable argus-ax25-vhf.service
|
||||
systemd:
|
||||
name: "digirig-direwolf"
|
||||
name: "argus-ax25-vhf"
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
|
||||
###################################################################################################
|
||||
# SYSTEMD: Net/Rom
|
||||
###################################################################################################
|
||||
|
||||
- name: Copy mheardd and netromd systemd service files
|
||||
ansible.builtin.copy:
|
||||
src: "templates/{{ item }}"
|
||||
dest: "/etc/systemd/system/{{ item }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
with_items:
|
||||
- mheardd.service
|
||||
- netromd.service
|
||||
register: services_copied
|
||||
|
||||
- name: Enable and start AX.25/NET/ROM daemons
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: "{{ services_copied.changed }}"
|
||||
with_items:
|
||||
- mheardd
|
||||
- netromd
|
||||
|
||||
###################################################################################################
|
||||
# SYSTEMD: NET/ROM network interface init
|
||||
# These get created when the service starts and they just stay running until you shut down the
|
||||
# service or reboot.
|
||||
###################################################################################################
|
||||
|
||||
- name: Install systemd unit file for NET/ROM network interfaces
|
||||
ansible.builtin.copy:
|
||||
src: "templates/netrom-init.service.j2"
|
||||
dest: "/etc/systemd/system/netrom-init.service"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
register: netrom_init_service
|
||||
|
||||
- name: Enable and start netrom-init service
|
||||
ansible.builtin.systemd:
|
||||
name: netrom-init
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: "{{ netrom_init_service.changed }}"
|
||||
|
||||
###################################################################################################
|
||||
# AX35 and NET/ROM Config
|
||||
###################################################################################################
|
||||
@@ -168,6 +107,32 @@
|
||||
- nrports
|
||||
- nrbroadcast
|
||||
|
||||
###################################################################################################
|
||||
# SYSTEMD: netromd and mheardd services
|
||||
###################################################################################################
|
||||
|
||||
- name: Copy mheardd and netromd systemd service files
|
||||
ansible.builtin.copy:
|
||||
src: "templates/{{ item }}"
|
||||
dest: "/etc/systemd/system/{{ item }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
with_items:
|
||||
- mheardd.service
|
||||
- netromd.service
|
||||
register: services_copied
|
||||
|
||||
- name: Enable and start mheardd and netromd services
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: "{{ services_copied.changed }}"
|
||||
with_items:
|
||||
- mheardd
|
||||
- netromd
|
||||
|
||||
###################################################################################################
|
||||
# UDEV RULES (keep these last)
|
||||
###################################################################################################
|
||||
+11
-5
@@ -1,19 +1,25 @@
|
||||
# udev rule to provide fixed device name for my Digirig and start/stop services automatically!
|
||||
|
||||
# This information was retrieved by the following. Assuming the radio USB sound card is hooked
|
||||
# up to /dev/ttyUSB0
|
||||
#
|
||||
# craig@scanner:~$ udevadm info /dev/ttyUSB0 | grep ID_SERIAL
|
||||
# This is how I found the serials, vendor and product id values:
|
||||
#
|
||||
# Plug in the digirig and not anything else so you know it's card card #1, then get the vendor and
|
||||
# product id values like this:
|
||||
#
|
||||
# $ udevadm info /dev/ttyUSB0 | grep ID_SERIAL
|
||||
# E: ID_SERIAL=Silicon_Labs_CP2102N_USB_to_UART_Bridge_Controller_809986b5195bed119acbed165820eef3
|
||||
# E: ID_SERIAL_SHORT=809986b5195bed119acbed165820eef3
|
||||
#
|
||||
|
||||
# $ sudo udevadm info -a /sys/class/sound/card1 | grep -E 'idVendor|idProduct'
|
||||
# ATTRS{idProduct}=="0012"
|
||||
# ATTRS{idVendor}=="0d8c"
|
||||
|
||||
# This creates /dev/radio/digirig-sound which is a USB sound card device
|
||||
# It does not matter what USB port it's plugged into, or how many other USB devices are also plugged in.
|
||||
# ---------------------------------------------------------------------------------------------------
|
||||
SUBSYSTEM=="tty", ENV{ID_SERIAL_SHORT}=="809986b5195bed119acbed165820eef3", SYMLINK+="radio/digirig-sound", MODE="660", GROUP="plugdev"
|
||||
|
||||
# This sets a custom sound card name of "digirig" in the Linux ALSA system.
|
||||
SUBSYSTEM=="sound", ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="0012", ATTR{id}="digirig"
|
||||
|
||||
# Automatically start direwolf bash script when the radio is connected. Identify the radio by the
|
||||
# unique setial number.
|
||||
+7
-7
@@ -1,14 +1,14 @@
|
||||
# This file is managed by BusNet Ansible.
|
||||
# This file is managed by Ansible.
|
||||
#
|
||||
# This service starts the direwolf/AX.25 stack bash script when the Digirig device is connected to
|
||||
# this computer. The bash script then initializes the Linux AX.25 stack.
|
||||
# This service starts the dedicated 2m AX.25 stack bash script when the Digirig device is connected
|
||||
# to this computer.
|
||||
#
|
||||
# There is a corresponding udev rule that triggers this service automatically when it detects that
|
||||
# the radio's USB devices are connected. There is also a udev rule that shuts it down when the USB
|
||||
# is disconnected.
|
||||
|
||||
[Unit]
|
||||
Description=Direwolf TNC and AX.25 Stack
|
||||
Description=Argus AX.25 VHF Stack
|
||||
#After=network.target
|
||||
|
||||
# Link the service life cycle to the hardware device /dev/radio/digirig-sound. I don't know why, but
|
||||
@@ -19,11 +19,11 @@ After=dev-radio-digirig\x2dsound.device
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/opt/busnet/direwolf/digirig-direwolf.sh
|
||||
ExecStart=/opt/argus/scripts/ax25-vhf.sh
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
User=busnet
|
||||
Group=busnet
|
||||
User=argus
|
||||
Group=argus
|
||||
# This tells systemd to kill all child processe started by the bash script.
|
||||
KillMode=control-group
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
#!/bin/bash
|
||||
# Start the AX.25 VHF Stack
|
||||
# @author Craig McDaniel
|
||||
#
|
||||
# This script runs Direwolf, socat and kissatach. It starts them in that order and makes sure they
|
||||
# all stay running and work together. If one crashes, this script stops everything. This effectively
|
||||
# sets up a AX.25 interface on a Linux computer using the Linux AX.25 stack.
|
||||
#
|
||||
# It's designed to be uses with systemd for things like auto start, auto re-start.
|
||||
#
|
||||
#
|
||||
# Here's a diagram of the stack this creates:
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# RF signals! _ RF signals!
|
||||
# \ _/
|
||||
# \ /
|
||||
# +-------+
|
||||
# | Radio | ----- RF signals!
|
||||
# +-------+
|
||||
# |
|
||||
# | Analog cable
|
||||
# |
|
||||
# +---------+
|
||||
# | Digirig |
|
||||
# +---------+
|
||||
# |
|
||||
# | USB sound card
|
||||
# |
|
||||
# +----|----------------------------------------------------------------------------+
|
||||
# | | This is your computer. The things in here are virtual components. |
|
||||
# | | |
|
||||
# | +-----------+ +-------+ +------------+ Linux kernel |
|
||||
# | | Direwolf | <---> | Socat | <----> | Kissattach | <------> ax0 interface |
|
||||
# | +-----------+ +-------+ +------------+ / | |
|
||||
# | | /--------+ | |
|
||||
# | AGWPE port / | |
|
||||
# | available for +---------------+ +------------------+ |
|
||||
# | use | mheard daemon | | netromd: NET/ROM | |
|
||||
# | +---------------+ | Daemoon. | |
|
||||
# | +------------------+ |
|
||||
# +---------------------------------------------------------------------------------+
|
||||
|
||||
# Command to execute direwolf including any options and location of config file.
|
||||
DIREWOLF_CMD="/usr/local/bin/direwolf -t 0 -X 1 -c /opt/argus/direwolf/config/digirig.conf"
|
||||
|
||||
# The AX.25 port for the radio defined in /etc/ax25/axports. Note that this is not the same thing as
|
||||
# the kernel AX.25 interfaces, which are named things like ax0, ax1, etc...
|
||||
AX25_PORT_NAME="digirig"
|
||||
|
||||
# The NET/ROM port for the radio defined in /etc/ax25/nrports. Note that this also is not the same
|
||||
# thing as the kernel NET/ROM interface like nr0, nr1, etc...
|
||||
NETROM_PORT_NAME="digirig-nr"
|
||||
|
||||
# The PTY/TTY (whatever it's called) that socat will create for kissattach
|
||||
TNC_DEV="/dev/radio/digirig-tnc"
|
||||
|
||||
# This is the socat command to that connects one end of a virtual pipe to Direwolf's KISS TCP port,
|
||||
# and the other end to the PTY/TTY. The IP and port specified here must match the Direwolf config
|
||||
# file.
|
||||
SOCAT_CMD="/usr/bin/socat PTY,raw,echo=0,link=${TNC_DEV} TCP4:127.0.0.1:8001"
|
||||
|
||||
# These are the commands to create the kernel AX.25 interface using the kissattach utility.
|
||||
KISSATTACH_CMD="/usr/sbin/kissattach ${TNC_DEV} ${AX25_PORT_NAME}"
|
||||
KISSPARAMS_CMD="kissparms -c 1 -p ${AX25_PORT_NAME}"
|
||||
|
||||
# This is for creating the NET/ROM kernel interface.
|
||||
NRATTACH_CMD="nrattach ${NETROM_PORT_NAME}"
|
||||
|
||||
# Cleanup the AX.25 stack
|
||||
cleanup_stack()
|
||||
{
|
||||
# Kill kissattach explicitly (it forks, so we can't track its PID)
|
||||
sudo pkill -f "kissattach ${TNC_DEV} ${AX25_PORT_NAME}"
|
||||
sleep 1
|
||||
|
||||
# Kill socat by PID
|
||||
if [ -n "$SOCAT_PID" ]; then
|
||||
sudo kill $SOCAT_PID 2>/dev/null
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
# Kill direwolf by PID and wait for it to finish
|
||||
if [ -n "$DIREWOLF_PID" ] && kill -0 $DIREWOLF_PID 2>/dev/null; then
|
||||
kill $DIREWOLF_PID 2>/dev/null
|
||||
wait $DIREWOLF_PID 2>/dev/null
|
||||
fi
|
||||
|
||||
# The file /etc/ax25/nrports mapps the $NETROM_PORT_NAME to a unique callsign. We need to
|
||||
# figure out what the associated callsign for the netrom port is.
|
||||
# Example: digirig-nr K0BIT-8 8BITS 235 NET/ROM Port
|
||||
local NETROM_CALLSIGN=$(grep "^${NETROM_PORT_NAME}" /etc/ax25/nrports | awk '{print $2}')
|
||||
|
||||
# make sure we actually have a corresponding NET/ROM device and callsign in nrports. If not,
|
||||
# then we can just be done right now.
|
||||
if [ -z "$NETROM_CALLSIGN" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Find all NET/ROM interfaces (like nr0, nr1, nr2, etc...) and check their callsigns.
|
||||
# Shut down any NET/ROM interface with the $NETROM_CALLSIGN attached to it.
|
||||
for IFACE in $(ip link show | grep -oE 'nr[0-9]+'); do
|
||||
# Get the callsign for this interface
|
||||
local IFACE_CALL=$(ip addr show $IFACE | grep 'netrom' | awk '{print $2}')
|
||||
|
||||
if [ "$IFACE_CALL" = "$NETROM_CALLSIGN" ]; then
|
||||
echo "Bringing down NET/ROM interface ${IFACE} ..."
|
||||
sudo ip link set $IFACE down
|
||||
return
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# Start the AX.25 stack
|
||||
start_stack()
|
||||
{
|
||||
# Start Direwolf in background
|
||||
$DIREWOLF_CMD &
|
||||
DIREWOLF_PID=$!
|
||||
# NOTE: If Direwolf encounters an error, it will just WAIT something like 15 seconds before
|
||||
# exiting. It does not fail fast. That means that the following check will pass, but then
|
||||
# we go to move on to create socat which will fail. I don't have a good solution for this
|
||||
# case just yet, but I'm recording this note here.
|
||||
if ! kill -0 $DIREWOLF_PID; then
|
||||
echo "Direwolf failed to start."
|
||||
cleanup_stack
|
||||
exit 1
|
||||
fi
|
||||
echo "Direwolf started (PID: $DIREWOLF_PID)"
|
||||
|
||||
# Start socat PTY bridge.
|
||||
# socat creates a full duplex/bidirectional pipe between a serial port ${TNC_DEV} and Direwolf's
|
||||
# KISS TCP interface, which is running on localhost:8001. The kissattach program needs a serial
|
||||
# port to work, and this is how we accomplish connecting kissattach to direwolf.
|
||||
sleep 3
|
||||
sudo $SOCAT_CMD &
|
||||
SOCAT_PID=$!
|
||||
if ! kill -0 $SOCAT_PID; then
|
||||
echo "Socat failed to start."
|
||||
cleanup_stack
|
||||
exit 1
|
||||
fi
|
||||
echo "socat started (PID: $SOCAT_PID)"
|
||||
|
||||
# Run kissatach to create an AX.25 network interface on the system.
|
||||
# Kissattach annoyingly forks itself in the background, so we can't directly monitor the process.
|
||||
# Kissattach cannot use KISS over TCP directly to Direwolf. It expects a serial terminal to exist,
|
||||
# which is why we use socat to create the pipe between Direwolf's KISS TCP port and this serial
|
||||
# device.
|
||||
sleep 1
|
||||
sudo $KISSATTACH_CMD
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "kissattach failed to start."
|
||||
cleanup_stack
|
||||
fi
|
||||
|
||||
# We have to set something on the AX.25 interface that Direwolf requires via kissparams.
|
||||
sudo $KISSPARAMS_CMD
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "kissparams failure detected."
|
||||
cleanup_stack
|
||||
fi
|
||||
|
||||
# We must run the nrattach command to create a kernel NET/ROM interface.
|
||||
sudo $NRATTACH_CMD
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Command ${NRATTACH_CMD} failed."
|
||||
cleanup_stack
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Restart mheardd daemon. If mheardd was started before ax1, ax2 or other AX.25 kernel interface
|
||||
# was created, and now we receive AX.25 packets on this new interface we just created, mheardd
|
||||
# just throws errors about a new, unknown interface. Ugh.
|
||||
if sudo systemctl is-enabled --quiet mheardd.service; then
|
||||
echo "Restarting mheardd..."
|
||||
sudo systemctl restart mheardd.service
|
||||
fi
|
||||
|
||||
# If netromd is not running, restart it. Otherwise, leave it alone.
|
||||
if sudo systemctl is-enabled --quiet netromd.service; then
|
||||
if ! sudo systemctl is-active --quiet netromd.service; then
|
||||
echo "Re-starting netromd..."
|
||||
sudo systemctl start netromd.service
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# This is our POSIX signal handler so we cleanly shut down before exiting.
|
||||
handle_signal()
|
||||
{
|
||||
echo "We received a SIGINT or SIGTERM signal. Shutting down VHF AX.25 stack."
|
||||
cleanup_stack
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
###################################################################################################
|
||||
#
|
||||
# MAIN ENTRY POINT
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "VHF AX.25 Stack Started"
|
||||
echo "======================================================================"
|
||||
echo ""
|
||||
|
||||
# This is the bash way of intercepting these signals. We execute the cleanup function when we receive
|
||||
# either one.
|
||||
trap handle_signal SIGINT SIGTERM
|
||||
|
||||
# Load required kernel modules
|
||||
echo "Loading kernel modules..."
|
||||
sudo modprobe ax25
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to load ax25 kernel module"
|
||||
exit 1
|
||||
fi
|
||||
sudo modprobe netrom
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to load netrom kernel module"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean up any orphaned kissattach processes from previous runs. We must do this because kissattach
|
||||
# forks itself in the background, and we therefore cannot keep track of its PID. We use pkill to
|
||||
# make sure no previous kissattach is running.
|
||||
sudo pkill -f "kissattach ${TNC_DEV} ${AX25_PORT_NAME}"
|
||||
sleep 1
|
||||
|
||||
# Note that we don't have to do the same for nrattach. nrattach runs and then exits.
|
||||
|
||||
# Start the AX.25 stack
|
||||
start_stack
|
||||
echo "All processes started. Monitoring via wait..."
|
||||
|
||||
# 'wait -n' waits for ANY background process to exit.
|
||||
# It returns as soon as Direwolf or Socat dies. Kissattach forks itself so we can't wait on it.
|
||||
wait -n
|
||||
|
||||
# If we get here, one of the processes died. Cleanup the stack and exit.
|
||||
cleanup_stack
|
||||
+8
-3
@@ -1,4 +1,4 @@
|
||||
# This file is managed by BusNet Ansible
|
||||
# This file is managed by Ansible
|
||||
#
|
||||
# This is the Direwolf configuration for connecting Direwolf to the Digirig USB sound card. This assumes
|
||||
# that we will operate using 1200 baud mode in 2 meters VHF with a dedicated radio for this purpose.
|
||||
@@ -6,7 +6,9 @@
|
||||
# There us a udev rule which creates "/dev/radio/digirig-sound" so that we do not have to worry about
|
||||
# what USB port or tty number is assigned when this device is connected to the computer.
|
||||
|
||||
ADEVICE plughw:Device,0
|
||||
# We create a custom ALSA sound card name of "digirig" in our udev rules. Direwolf uses ALSA directly,
|
||||
# so this tells Direwolf to use the "digirig" sound card, subdevice #0 (there is only 1 subdevice).
|
||||
ADEVICE plughw:CARD=digirig,DEV=0
|
||||
|
||||
# The custom udev rule makes this device available by name.
|
||||
PTT /dev/radio/digirig-sound RTS
|
||||
@@ -19,4 +21,7 @@ MODEM 1200
|
||||
FX25TX 1
|
||||
|
||||
AGWPORT 8000
|
||||
KISSPORT 8001
|
||||
KISSPORT 8001
|
||||
|
||||
# In the future, I might set up a RV BBS! I would beacon it here.
|
||||
#PBEACON every=1 overlay=S symbol="bus" lat=29.958260914551104 long=-90.05442788530239 comment="I'm like testing APRS, man" via=WIDE1-1,WIDE2-1
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
[Unit]
|
||||
Description=NET/ROM Routing Daemon
|
||||
After=digirig-direwolf.service
|
||||
BindTo=digirig-direwolf.service
|
||||
After=ax25-vhf.service
|
||||
BindTo=ax25-vhf.service
|
||||
|
||||
# systemd has trouble with this daemon. Presumably it's old code and systemd cannot determine if
|
||||
# the daemon starts. These settings seem to work.
|
||||
Regular → Executable
+109
-26
@@ -16,19 +16,57 @@
|
||||
# - Run kissattach to the socat PTY to create a kernel AX.25 interface.
|
||||
# - Make sure mheardd daemon is restarted so it can see new AX.25 interface.
|
||||
#
|
||||
# Here's a diagram of the stack this creates:
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# RF signals! _ RF signals!
|
||||
# \ _/
|
||||
# \ /
|
||||
# +-------+ FT991a has built in CAT and sound card accessible
|
||||
# | Radio | ----- via USB socket on rear of radio.
|
||||
# +-------+
|
||||
# |
|
||||
# | USB
|
||||
# |
|
||||
# +----|----------------------------------------------------------------------------+
|
||||
# | | This is your computer. The things in here are virtual components. |
|
||||
# | | |
|
||||
# | +-----------+ +-------+ +------------+ Linux kernel |
|
||||
# | | Direwolf | <---> | Socat | <----> | Kissattach | <------> ax2 interface |
|
||||
# | +-----------+ +-------+ +------------+ / | |
|
||||
# | | /--------+ | |
|
||||
# | AGWPE port / | |
|
||||
# | available for +---------------+ +------------------+ |
|
||||
# | use | mheard daemon | | netromd: NET/ROM | |
|
||||
# | +---------------+ | Daemoon. | |
|
||||
# | +------------------+ |
|
||||
# +---------------------------------------------------------------------------------+
|
||||
|
||||
# === Configuration ===
|
||||
# Direwolf executable
|
||||
DIREWOLF_PATH="/usr/local/bin/direwolf"
|
||||
PORT_NAME="ft991a"
|
||||
|
||||
# The AX.25 port for the radio defined in /etc/ax25/axports. Note that this is not the same thing as
|
||||
# the kernel AX.25 interfaces, which are named things like ax0, ax1, etc...
|
||||
AX25_PORT_NAME="ft991a"
|
||||
|
||||
# The NET/ROM port for the radio defined in /etc/ax25/nrports. Note that this also is not the same
|
||||
# thing as the kernel NET/ROM interface like nr0, nr1, etc...
|
||||
NETROM_PORT_NAME="ft991a-nr"
|
||||
|
||||
# The PTY/TTY (whatever it's called) that socat will create for kissattach
|
||||
TNC_DEV="/dev/radio/ft991a-tnc"
|
||||
|
||||
# The direwolf KISS TCP port that socat will connect to
|
||||
KISS_TCP_PORT=8006
|
||||
NR_PORT="ft991a-nr"
|
||||
POLL_INTERVAL=5
|
||||
|
||||
# Rigctl stuff
|
||||
RIGCTLD_HOST="localhost"
|
||||
RIGCTLD_PORT=4000
|
||||
POLL_RETRIES=1
|
||||
POLL_INTERVAL=5
|
||||
|
||||
# Frequency ranges (Hz)
|
||||
# Frequency ranges in Hz for the bands tha radio supports. This is how we know what direwolf config
|
||||
# to use.
|
||||
HF_MIN=1800000
|
||||
HF_MAX=30000000
|
||||
VHF_MIN=144390000
|
||||
@@ -37,9 +75,9 @@ UHF_MIN=432000000
|
||||
UHF_MAX=433000000
|
||||
|
||||
# Config files per band
|
||||
CONFIG_HF="/opt/busnet/direwolf/config/ft991a-hf.conf"
|
||||
CONFIG_VHF="/opt/busnet/direwolf/config/ft991a-vhf.conf"
|
||||
CONFIG_UHF="/opt/busnet/direwolf/config/ft991a-uhf.conf"
|
||||
CONFIG_HF="/opt/argus/direwolf/config/ft991a-hf.conf"
|
||||
CONFIG_VHF="/opt/argus/direwolf/config/ft991a-vhf.conf"
|
||||
CONFIG_UHF="/opt/argus/direwolf/config/ft991a-uhf.conf"
|
||||
|
||||
# State tracking
|
||||
CUR_BAND="NONE"
|
||||
@@ -101,6 +139,8 @@ cleanup_stack()
|
||||
sudo pkill -f "kissattach ${TNC_DEV}"
|
||||
sleep 1
|
||||
|
||||
# Note that we don't have to do the same for nrattach. nrattach runs and then exits.
|
||||
|
||||
if [ -n "$SOCAT_PID" ]; then
|
||||
sudo kill $SOCAT_PID 2>/dev/null
|
||||
sleep 1
|
||||
@@ -111,6 +151,26 @@ cleanup_stack()
|
||||
wait $DIREWOLF_PID 2>/dev/null
|
||||
fi
|
||||
|
||||
# The file /etc/ax25/nrports mapps the $NETROM_PORT_NAME to a unique callsign. We need to
|
||||
# figure out what the associated callsign for the netrom port is.
|
||||
# Example: digirig-nr K0BIT-8 8BITS 235 NET/ROM Port
|
||||
local NETROM_CALLSIGN=$(grep "^${NETROM_PORT_NAME}" /etc/ax25/nrports | awk '{print $2}')
|
||||
|
||||
# Find all NET/ROM interfaces (like nr0, nr1, nr2, etc...) and check their callsigns.
|
||||
# Shut down any NET/ROM interface with the $NETROM_CALLSIGN attached to it.
|
||||
if [ -n "$NETROM_CALLSIGN" ]; then
|
||||
for IFACE in $(ip link show | grep -oE 'nr[0-9]+'); do
|
||||
# Get the callsign for this interface
|
||||
local IFACE_CALL=$(ip addr show $IFACE | grep 'netrom' | awk '{print $2}')
|
||||
|
||||
if [ "$IFACE_CALL" = "$NETROM_CALLSIGN" ]; then
|
||||
echo "Bringing down NET/ROM interface ${IFACE} ..."
|
||||
sudo ip link set $IFACE down
|
||||
return
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "FT991a AX.25 ${CUR_BAND} stack is now shut down."
|
||||
CUR_BAND="NONE"
|
||||
DIREWOLF_PID=""
|
||||
@@ -136,30 +196,30 @@ start_stack()
|
||||
|
||||
echo "Starting $BAND stack..."
|
||||
|
||||
# Start Direwolf
|
||||
echo "Starting Direwolf..."
|
||||
# Start Direwolf in background
|
||||
$DIREWOLF_PATH -t 0 -X 1 -c "$CONFIG" &
|
||||
DIREWOLF_PID=$!
|
||||
sleep 2
|
||||
|
||||
# NOTE: If Direwolf encounters an error, it will just WAIT something like 15 seconds before
|
||||
# exiting. It does not fail fast. That means that the following check will pass, but then
|
||||
# we go to move on to create socat which will fail. I don't have a good solution for this
|
||||
# case just yet, but I'm recording this note here.
|
||||
if ! kill -0 $DIREWOLF_PID 2>/dev/null; then
|
||||
echo "FATAL: Direwolf failed to start" >&2
|
||||
echo "Direwolf failed to start" >&2
|
||||
DIREWOLF_PID=""
|
||||
return 1
|
||||
fi
|
||||
echo "Direwolf started (PID: $DIREWOLF_PID)"
|
||||
|
||||
# Start socat PTY bridge
|
||||
echo "Starting socat PTY bridge..."
|
||||
sleep 3
|
||||
sudo socat PTY,raw,echo=0,link=$TNC_DEV TCP4:127.0.0.1:$KISS_TCP_PORT &
|
||||
SOCAT_PID=$!
|
||||
sleep 1
|
||||
|
||||
if ! kill -0 $SOCAT_PID 2>/dev/null; then
|
||||
echo "FATAL: socat failed to start" >&2
|
||||
echo "socat failed to start" >&2
|
||||
cleanup_stack
|
||||
return 1
|
||||
fi
|
||||
echo "socat started (PID: $SOCAT_PID)"
|
||||
|
||||
# Wait for PTY device to exist
|
||||
local WAIT_COUNT=0
|
||||
@@ -169,7 +229,7 @@ start_stack()
|
||||
done
|
||||
|
||||
if [ ! -L $TNC_DEV ]; then
|
||||
echo "FATAL: PTY device $TNC_DEV not created" >&2
|
||||
echo "PTY device $TNC_DEV not created" >&2
|
||||
cleanup_stack
|
||||
return 1
|
||||
fi
|
||||
@@ -177,7 +237,7 @@ start_stack()
|
||||
|
||||
# Kissattach connects the PTY device created by socat to the kernel.
|
||||
echo "Running kissattach..."
|
||||
sudo kissattach $TNC_DEV $PORT_NAME
|
||||
sudo kissattach $TNC_DEV $AX25_PORT_NAME
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "FATAL: kissattach failed" >&2
|
||||
cleanup_stack
|
||||
@@ -189,27 +249,43 @@ start_stack()
|
||||
echo "Setting kissparms..."
|
||||
case $BAND in
|
||||
HF)
|
||||
sudo kissparms -p $PORT_NAME -c 1 -t 350
|
||||
sudo kissparms -p $AX25_PORT_NAME -c 1 -t 350
|
||||
echo "Set kissparams for HF: window=1, txdelay=350ms"
|
||||
;;
|
||||
VHF)
|
||||
sudo kissparms -p $PORT_NAME -c 3 -t 200
|
||||
sudo kissparms -p $AX25_PORT_NAME -c 3 -t 200
|
||||
echo "Set kissparams for VHF: window=3, txdelay=200ms"
|
||||
;;
|
||||
UHF)
|
||||
sudo kissparms -p $PORT_NAME -c 3 -t 150
|
||||
sudo kissparms -p $AX25_PORT_NAME -c 3 -t 150
|
||||
echo "Set kissparams for UHF: window=3, txdelay=150ms"
|
||||
;;
|
||||
esac
|
||||
|
||||
# We must run the nrattach command to create a kernel NET/ROM interface.
|
||||
sudo nrattach $NETROM_PORT_NAME
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "nrattach failed."
|
||||
cleanup_stack
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Restart mheardd daemon. If mheardd was started before ax1, ax2 or other AX.25 kernel interface
|
||||
# was created, and now we receive AX.25 packets on this new interface we just created, mheardd
|
||||
# just throws errors about a new, unknown interface. Ugh.
|
||||
if systemctl is-active --quiet mheardd.service; then
|
||||
if sudo systemctl is-enabled --quiet mheardd.service; then
|
||||
echo "Restarting mheardd..."
|
||||
sudo systemctl restart mheardd.service
|
||||
fi
|
||||
|
||||
# If netromd is not running, restart it. Otherwise, leave it alone.
|
||||
if sudo ystemctl is-enabled --quiet netromd.service; then
|
||||
if ! sudo systemctl is-active --quiet netromd.service; then
|
||||
echo "Re-starting netromd..."
|
||||
sudo systemctl start netromd.service
|
||||
fi
|
||||
fi
|
||||
|
||||
CUR_BAND="$BAND"
|
||||
echo "FT991a AX.25 ${CUR_BAND} stack is online."
|
||||
echo ""
|
||||
@@ -241,9 +317,16 @@ echo ""
|
||||
# either one.
|
||||
trap handle_signal SIGINT SIGTERM
|
||||
|
||||
# Check if Direwolf exists
|
||||
if [ ! -f $DIREWOLF_PATH ]; then
|
||||
echo "FATAL: Direwolf executable not found at $DIREWOLF_PATH" >&2
|
||||
# Load required kernel modules
|
||||
echo "Loading kernel modules..."
|
||||
sudo modprobe ax25
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to load ax25 kernel module"
|
||||
exit 1
|
||||
fi
|
||||
sudo modprobe netrom
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to load netrom kernel module"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
#!/bin/bash
|
||||
# @author Craig McDaniel
|
||||
#
|
||||
# This script runs Direwolf, socat and kissatach. It starts them in that order and makes sure they
|
||||
# all stay running and work together. If one crashes, this script stops everything. This effectively
|
||||
# sets up a AX.25 interface on a Linux computer using the Linux AX.25 stack.
|
||||
#
|
||||
# It's designed to be uses with systemd for things like auto start, auto re-start.
|
||||
#
|
||||
#
|
||||
# RF signals! _ RF signals!
|
||||
# \ _/
|
||||
# \ /
|
||||
# +-------+
|
||||
# | Radio | ----- RF signals!
|
||||
# +-------+
|
||||
# |
|
||||
# | Analog cable
|
||||
# |
|
||||
# +---------+
|
||||
# | Digirig |
|
||||
# +---------+
|
||||
# |
|
||||
# | USB sound card
|
||||
# |
|
||||
# +----|----------------------------------------------------------------------------+
|
||||
# | | This is your computer. The things in here are virtual components. |
|
||||
# | | |
|
||||
# | +-----------+ +-------+ +------------+ Linux kernel |
|
||||
# | | Direwolf | <---> | Socat | <----> | Kissattach | <------> ax0 interface |
|
||||
# | +-----------+ +-------+ +------------+ / | |
|
||||
# | | /--------+ | |
|
||||
# | AGWPE port / | |
|
||||
# | available for +---------------+ +------------------+ |
|
||||
# | use | mheard daemon | | netromd: NET/ROM | |
|
||||
# | +---------------+ | Daemoon. | |
|
||||
# | +------------------+ |
|
||||
# +---------------------------------------------------------------------------------+
|
||||
|
||||
# Configuration
|
||||
DIREWOLF_CMD="/usr/local/bin/direwolf -t 0 -X 1 -c /opt/busnet/direwolf/config/digirig.conf"
|
||||
SOCAT_CMD="/usr/bin/socat PTY,raw,echo=0,link=/dev/radio/digirig-tnc TCP4:127.0.0.1:8001"
|
||||
KISSATTACH_CMD="/usr/sbin/kissattach /dev/radio/digirig-tnc digirig"
|
||||
KISSPARAMS_CMD="kissparms -c 1 -p digirig"
|
||||
|
||||
cleanup() {
|
||||
echo
|
||||
echo "Exit signal detected. Cleaning up..."
|
||||
trap - SIGTERM # prevent recursion
|
||||
kill 0
|
||||
exit
|
||||
}
|
||||
|
||||
# Trap exit signals
|
||||
trap cleanup SIGINT SIGTERM
|
||||
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "Starting Direwolf..."
|
||||
echo "======================================================================"
|
||||
echo
|
||||
$DIREWOLF_CMD &
|
||||
DIREWOLF_PID=$!
|
||||
sleep 1
|
||||
if ! kill -0 $DIREWOLF_PID; then
|
||||
echo "Direwolf failed to start."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Wait 3 seconds for Direwolf to initialize, then start socat.
|
||||
# socat creates a full duplex/bidirectional pipe between a serial port /dev/radio/digirig-tnc and
|
||||
# Direwolf's KISS TCP interface, which is running on localhost:8001. The kissattach program needs
|
||||
# a serial port to work, and this is how we accomplish connecting kissattach to direwolf.
|
||||
sleep 3
|
||||
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "Starting socat..."
|
||||
echo "======================================================================"
|
||||
echo
|
||||
sudo $SOCAT_CMD &
|
||||
SOCAT_PID=$!
|
||||
if ! kill -0 $SOCAT_PID; then
|
||||
echo "Socat failed to start."
|
||||
kill $DIREWOLF_PID
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Run kissatach to create an AX.25 network interface on the system.
|
||||
#
|
||||
# Kissattach annoyingly forks itself in the background, so we can't directly monitor the process.
|
||||
# We rely on the control-group feature of systemd to kill all child processes for us, even if
|
||||
# they fork!
|
||||
#
|
||||
# Kissattach cannot use KISS over TCP directly to Direwolf. It expects a serial terminal to exist,
|
||||
# which is why we use socat to create the pipe between Direwolf's KISS TCP port and this serial
|
||||
# device.
|
||||
sleep 1
|
||||
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "Starting kissattach and setting kissparams..."
|
||||
echo "======================================================================"
|
||||
echo
|
||||
sudo $KISSATTACH_CMD
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "kissattach failed to start."
|
||||
cleanup
|
||||
fi
|
||||
|
||||
# We have to set something on the AX.25 interface that Direwolf requires.
|
||||
sudo $KISSPARAMS_CMD
|
||||
|
||||
echo
|
||||
echo "All processes started. Monitoring via wait..."
|
||||
|
||||
# 'wait -n' waits for ANY background process to exit.
|
||||
# It returns as soon as Direwolf or Socat dies.
|
||||
wait -n
|
||||
|
||||
# If we get here, one of the processes died.
|
||||
cleanup
|
||||
@@ -1,22 +0,0 @@
|
||||
[Unit]
|
||||
Description=Initialize NET/ROM Interfaces at Boot
|
||||
Documentation=man:nrattach(8)
|
||||
After=network.target
|
||||
Before=digirig-direwolf.service ft991a-direwolf.service mheardd.service netromd.service
|
||||
ConditionPathExists=/etc/ax25/nrports
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
|
||||
# Create NET/ROM interfaces for each port in nrports
|
||||
# nrattach finds first free device: digirig-nr gets nr0, ft991a-nr gets nr1
|
||||
ExecStart=/usr/sbin/nrattach digirig-nr
|
||||
ExecStart=/usr/sbin/nrattach ft991a-nr
|
||||
|
||||
# On stop/shutdown, bring down the interfaces cleanly
|
||||
ExecStop=/usr/sbin/ifconfig nr0 down
|
||||
ExecStop=/usr/sbin/ifconfig nr1 down
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user