ansible revamp dir structure
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
[all]
|
||||
scanner.busnet
|
||||
argus.busnet
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
# scanner.busnet
|
||||
# argus.busnet
|
||||
#
|
||||
|
||||
---
|
||||
- name: Install and Configure Various Things on scanner.busnet
|
||||
hosts: scanner.busnet
|
||||
- name: Install and Configure Various Things on argus.busnet
|
||||
hosts: argus.busnet
|
||||
become: true
|
||||
gather_facts: true
|
||||
tasks:
|
||||
- name: Set up base AX.25 stack with Digirig and dedicated VHF radio
|
||||
ansible.builtin.import_role:
|
||||
name: scanner_digirig
|
||||
name: argus_ax25
|
||||
when: run_ax25 is defined and run_ax25 | bool
|
||||
|
||||
- name: Set up base AX.25 stack with Digirig and dedicated VHF radio
|
||||
- name: Set up APRS listener using AirSpy
|
||||
ansible.builtin.import_role:
|
||||
name: scanner_airspy_aprs
|
||||
name: argus_aprs_airspy
|
||||
when: run_airspy_aprs is defined and run_airspy_aprs | bool
|
||||
|
||||
- name: Set up udev rules, rigctld and direwolf for Yaesu FT991-A
|
||||
ansible.builtin.import_role:
|
||||
name: scanner_ft991a
|
||||
name: argus_ft991a
|
||||
when: run_ft991a is defined and run_ft991a | bool
|
||||
|
||||
- name: Pat
|
||||
ansible.builtin.import_role:
|
||||
name: scanner_pat
|
||||
name: argus_pat
|
||||
when: run_pat is defined and run_pat | bool
|
||||
|
||||
- name: Install and configure PulseAudio for network audio
|
||||
ansible.builtin.import_role:
|
||||
name: argus_pulseaudio
|
||||
when: run_pulseaudio is defined and run_pulseaudio | bool
|
||||
|
||||
- name: Hamlib
|
||||
ansible.builtin.import_role:
|
||||
name: hamlib
|
||||
when: run_hamlib is defined and run_hamlib | bool
|
||||
|
||||
- name: Install and configure PulseAudio for network audio
|
||||
ansible.builtin.import_role:
|
||||
name: scanner_pulseaudio
|
||||
when: run_pulseaudio is defined and run_pulseaudio | bool
|
||||
@@ -1 +0,0 @@
|
||||
../../templates/
|
||||
@@ -55,6 +55,7 @@
|
||||
- ax25-tools
|
||||
- ax25-apps
|
||||
- libax25
|
||||
- socat
|
||||
state: present
|
||||
|
||||
###################################################################################################
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
# name callsign speed paclen window description
|
||||
#
|
||||
digirig K0BIT-1 9600 255 5 VHF Port using ICOM IC-V8000 and Compactenna 2M/440+
|
||||
airspy N0CAL-1 9600 255 5 AirSpy for VHF packet receive only.
|
||||
airspy APRS-1 9600 255 5 AirSpy for VHF packet receive only.
|
||||
ft991a K0BIT-2 9600 255 2 Used when the FT-991A radio is connected
|
||||
|
||||
@@ -1,33 +1,43 @@
|
||||
# Role: scanner_direwolf
|
||||
# This installs and configures direwolf on the scanner.bus computer
|
||||
# Role: argus_ft991a
|
||||
#
|
||||
# This role installs and configures Hamlib, PulseAudio and an AX.25 stack for the FT-991a! This
|
||||
# radio is very vesatile, so this role does numerous things.
|
||||
#
|
||||
# - Set up udev rules to make special device drivers for the Yaesu 991 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.
|
||||
#
|
||||
# - Set up systemd service to start Direwolf when the radio is connected via USB, and to stop it
|
||||
# when the radio is disconnected.
|
||||
# - These same udev rules also set up a special ALSA name for the sound card detected with the
|
||||
# FT991a so that when specifing the ALSA device, it can be referenced using a useful name.
|
||||
#
|
||||
# - Download, compile and install direwolf from source.
|
||||
# - Set up rigctld daemon that allows anything on the network to use hamlib for radio control.
|
||||
#
|
||||
# - Copy configuration files
|
||||
# - Set up systemd service to start an AX.25 stack when the radio is connected via USB and powered
|
||||
# on, and shut down the stack when the radio is powered off. Also restarts Direwolf with a separate
|
||||
# config for each band: HF, VHF, UHF with the correct modem settings. Auto detect frequency change
|
||||
# and auto restart Direwolf/AX.25 stack.
|
||||
#
|
||||
# - Creates a psuedo ALSA device that hooks into PulseAudio so that devices that only expect ALSA
|
||||
# to work, can use the psuedo device normally. This is for this computer only. Of course because
|
||||
# we run PulseAudio, the source and sink of the FT991-A sound card is available for use by other
|
||||
# computers on the network!
|
||||
|
||||
- name: Create various directories
|
||||
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:
|
||||
@@ -36,127 +46,29 @@
|
||||
- audio
|
||||
- plugdev
|
||||
|
||||
###################################################################################################
|
||||
# Compile and install Direwolf from source
|
||||
###################################################################################################
|
||||
|
||||
#- name: Install correct prerequite packages when running Ubuntu Noble
|
||||
# ansible.builtin.include_tasks: ubuntu_noble.yml
|
||||
# when: ansible_distribution == "Ubuntu" and ansible_distribution_release == "noble"
|
||||
|
||||
#- name: Git stuff
|
||||
# ansible.builtin.command:
|
||||
# cmd: "git config --global --add safe.directory /opt/busnet/direwolf/source"
|
||||
|
||||
#- name: Checkout direwolf source
|
||||
# ansible.builtin.git:
|
||||
# repo: "https://www.github.com/wb2osz/direwolf"
|
||||
# dest: /opt/busnet/direwolf/source
|
||||
# version: 1.7
|
||||
|
||||
#- name: Create the build directory
|
||||
# ansible.builtin.file:
|
||||
# path: /opt/busnet/direwolf/source/build
|
||||
# state: directory
|
||||
# mode: '0755'
|
||||
|
||||
#- name: Configure the build with cmake
|
||||
# ansible.builtin.command:
|
||||
# cmd: "cmake .."
|
||||
# chdir: /opt/busnet/direwolf/source/build
|
||||
|
||||
#- name: Build direwolf
|
||||
# ansible.builtin.command:
|
||||
# cmd: "make -j4"
|
||||
# chdir: /opt/busnet/direwolf/source/build
|
||||
|
||||
#- name: make install
|
||||
# community.general.make:
|
||||
# chdir: /opt/busnet/direwolf/source/build
|
||||
# target: install
|
||||
|
||||
#- name: Copy ft991a_monitor.py auto frequency sensing script
|
||||
# copy:
|
||||
# src: "templates/ft991a_monitor.py"
|
||||
# dest: "/opt/busnet/direwolf/ft991a_monitor.py"
|
||||
# owner: busnet
|
||||
# group: busnet
|
||||
# mode: "0755"
|
||||
|
||||
- name: Copy ft991a-monitor.sh script
|
||||
copy:
|
||||
src: "templates/ft991a-monitor.sh"
|
||||
dest: "/opt/busnet/direwolf/ft991a-monitor.sh"
|
||||
owner: busnet
|
||||
group: busnet
|
||||
mode: "0755"
|
||||
|
||||
- name: Copy Direwolf HF config for Yaesu FT-991a
|
||||
template:
|
||||
src: "templates/ft991a-direwolf-hf.conf.j2"
|
||||
dest: "/opt/busnet/direwolf/config/ft991a-hf.conf"
|
||||
owner: busnet
|
||||
group: busnet
|
||||
|
||||
- name: Copy Direwolf VHF config for Yaesu FT-991a
|
||||
template:
|
||||
src: "templates/ft991a-direwolf-vhf.conf.j2"
|
||||
dest: "/opt/busnet/direwolf/config/ft991a-vhf.conf"
|
||||
owner: busnet
|
||||
group: busnet
|
||||
|
||||
- name: Copy Direwolf UHF config for Yaesu FT-991a
|
||||
template:
|
||||
src: "templates/ft991a-direwolf-uhf.conf.j2"
|
||||
dest: "/opt/busnet/direwolf/config/ft991a-uhf.conf"
|
||||
owner: busnet
|
||||
group: busnet
|
||||
|
||||
###################################################################################################
|
||||
# SYSTEMD
|
||||
###################################################################################################
|
||||
|
||||
# udev rules start this automatically when the radio USB is connected, and stop when disconnected.
|
||||
- name: Install systemd unit file for rigctld and Yaesu FT-991a
|
||||
template:
|
||||
src: "templates/ft991a-rigctld.service.j2"
|
||||
dest: "/etc/systemd/system/ft991a-rigctld.service"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Enable ft991a-rigctld service
|
||||
systemd:
|
||||
name: "ft991a-rigctld"
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
|
||||
# udev rules start this automatically when the radio USB is connected, and stop when disconnected.
|
||||
- name: Install systemd unit file for Direwolf and Yaesu FT-991a
|
||||
template:
|
||||
src: "templates/ft991a-direwolf.service.j2"
|
||||
dest: "/etc/systemd/system/ft991a-direwolf.service"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Enable ft991a-direwolf service
|
||||
systemd:
|
||||
name: "ft991a-direwolf"
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
|
||||
###################################################################################################
|
||||
# ALSA CONFIGURATION
|
||||
###################################################################################################
|
||||
|
||||
- name: Copy /etc/asound.conf
|
||||
template:
|
||||
src: "templates/ft991a-asound.conf.j2"
|
||||
dest: "/etc/asound.conf"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
- name: Configure ALSA pseudo-devices for FT991a in argus user's .asoundrc
|
||||
ansible.builtin.blockinfile:
|
||||
path: /opt/argus/.asoundrc # This is the home dir of argus user!
|
||||
block: |
|
||||
pcm.ft991a_rx {
|
||||
type pulse
|
||||
device "alsa_input.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo"
|
||||
}
|
||||
pcm.ft991a_tx {
|
||||
type pulse
|
||||
device "alsa_output.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo"
|
||||
}
|
||||
ctl.ft991a_rx { type pulse }
|
||||
ctl.ft991a_tx { type pulse }
|
||||
marker: "# {mark} ANSIBLE MANAGED BLOCK - FT991A DO NOT EDIT THIS"
|
||||
create: yes
|
||||
owner: argus
|
||||
group: argus
|
||||
mode: '0644'
|
||||
|
||||
###################################################################################################
|
||||
# UDEV RULES
|
||||
@@ -179,3 +91,114 @@
|
||||
ansible.builtin.command:
|
||||
cmd: "udevadm trigger"
|
||||
when: ft991a_udev_result.changed
|
||||
|
||||
###################################################################################################
|
||||
# AX.25 bash script and Direwolf configuration
|
||||
###################################################################################################
|
||||
|
||||
#- name: Install correct prerequite packages when running Ubuntu Noble
|
||||
# ansible.builtin.include_tasks: ubuntu_noble.yml
|
||||
# when: ansible_distribution == "Ubuntu" and ansible_distribution_release == "noble"
|
||||
|
||||
#- name: Git stuff
|
||||
# ansible.builtin.command:
|
||||
# cmd: "git config --global --add safe.directory /opt/argus/direwolf/source"
|
||||
|
||||
#- name: Checkout direwolf source
|
||||
# ansible.builtin.git:
|
||||
# repo: "https://www.github.com/wb2osz/direwolf"
|
||||
# dest: /opt/argus/direwolf/source
|
||||
# version: 1.7
|
||||
|
||||
#- name: Create the build directory
|
||||
# ansible.builtin.file:
|
||||
# path: /opt/argus/direwolf/source/build
|
||||
# state: directory
|
||||
# mode: '0755'
|
||||
|
||||
#- name: Configure the build with cmake
|
||||
# ansible.builtin.command:
|
||||
# cmd: "cmake .."
|
||||
# chdir: /opt/argus/direwolf/source/build
|
||||
|
||||
#- name: Build direwolf
|
||||
# ansible.builtin.command:
|
||||
# cmd: "make -j4"
|
||||
# chdir: /opt/argus/direwolf/source/build
|
||||
|
||||
#- name: make install
|
||||
# community.general.make:
|
||||
# chdir: /opt/argus/direwolf/source/build
|
||||
# target: install
|
||||
|
||||
#- name: Copy ft991a_monitor.py auto frequency sensing script
|
||||
# copy:
|
||||
# src: "templates/ft991a_monitor.py"
|
||||
# dest: "/opt/argus/direwolf/ft991a_monitor.py"
|
||||
# owner: argus
|
||||
# group: argus
|
||||
# mode: "0755"
|
||||
|
||||
- name: Copy ft991a-monitor.sh script
|
||||
copy:
|
||||
src: "templates/ft991a-monitor.sh"
|
||||
dest: "/opt/argus/scripts/ft991a-monitor.sh"
|
||||
owner: argus
|
||||
group: argus
|
||||
mode: "0755"
|
||||
|
||||
- name: Copy Direwolf HF config for Yaesu FT-991a
|
||||
template:
|
||||
src: "templates/ft991a-direwolf-hf.conf.j2"
|
||||
dest: "/opt/argus/direwolf/config/ft991a-hf.conf"
|
||||
owner: argus
|
||||
group: argus
|
||||
|
||||
- name: Copy Direwolf VHF config for Yaesu FT-991a
|
||||
template:
|
||||
src: "templates/ft991a-direwolf-vhf.conf.j2"
|
||||
dest: "/opt/argus/direwolf/config/ft991a-vhf.conf"
|
||||
owner: argus
|
||||
group: argus
|
||||
|
||||
- name: Copy Direwolf UHF config for Yaesu FT-991a
|
||||
template:
|
||||
src: "templates/ft991a-direwolf-uhf.conf.j2"
|
||||
dest: "/opt/argus/direwolf/config/ft991a-uhf.conf"
|
||||
owner: argus
|
||||
group: argus
|
||||
|
||||
###################################################################################################
|
||||
# SYSTEMD
|
||||
###################################################################################################
|
||||
|
||||
# udev rules start this automatically when the radio USB is connected, and stop when disconnected.
|
||||
- name: Install systemd unit file for argus-rigctld-ft991a
|
||||
template:
|
||||
src: "templates/argus-rigctld-ft991a.service.j2"
|
||||
dest: "/etc/systemd/system/argus-rigctld-ft991a.service"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Enable argus-rigctld-ft991a service
|
||||
systemd:
|
||||
name: "argus-rigctld-ft991a"
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
|
||||
# udev rules start this automatically when the radio USB is connected, and stop when disconnected.
|
||||
- name: Install systemd unit file argus-ax25-ft991a
|
||||
template:
|
||||
src: "templates/argus-ax25-ft991a.service.j2"
|
||||
dest: "/etc/systemd/system/argus-ax25-ft991a.service"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Enable argus-ax25-ft991a.service
|
||||
systemd:
|
||||
name: "argus-ax25-ft991a"
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
# udev rule to provide fixed device name for the Yeasu FT-991a and start/stop services automatically!
|
||||
|
||||
# This information was retrieved by the following. Assuming the radio USB is hooked up to /dev/ttyUSB0
|
||||
# and nothing else is plugged into the USB at the moment.
|
||||
#
|
||||
# craig@scanner:~$ udevadm info /dev/ttyUSB0 | grep ID_SERIAL
|
||||
# $ sudo udevadm info /dev/ttyUSB0 | grep ID_SERIAL
|
||||
# E: ID_SERIAL=Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_01A9F7D6
|
||||
# E: ID_SERIAL_SHORT=01A9F7D6
|
||||
#
|
||||
|
||||
# $ sudo udevadm info -a /sys/class/sound/card1 | grep -E 'idVendor|idProduct'
|
||||
# ATTRS{idProduct}=="29b3"
|
||||
# ATTRS{idVendor}=="08bb"
|
||||
|
||||
# This creates /dev/radio/ft991a-00 (CAT control) and /dev/radio/ft991a-01 (sound)
|
||||
# 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}=="01A9F7D6", SYMLINK+="radio/ft991a-$env{ID_USB_INTERFACE_NUM}", MODE="660", GROUP="plugdev"
|
||||
|
||||
# This sets a custom sound card name of "ft991a" in the Linux ALSA system.
|
||||
SUBSYSTEM=="sound", ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="29b3", ATTR{id}="ft991a"
|
||||
|
||||
# Automatically start rigctld and direwolf when the radio is connected. Identify the radio by the
|
||||
# unique setial number.
|
||||
|
||||
+5
-6
@@ -1,4 +1,4 @@
|
||||
# This file is managed by BusNet Ansible.
|
||||
# This file is managed by Ansible.
|
||||
#
|
||||
# This service starts Direwolf when the Yeasu FT-991A radio USB is connected to this computer.
|
||||
#
|
||||
@@ -7,7 +7,7 @@
|
||||
# is disconnected.
|
||||
|
||||
[Unit]
|
||||
Description=Direwolf TNC for Yaesu FT-991a Auto Frequency Sensing
|
||||
Description=FT-991A AX.25 stack
|
||||
|
||||
# Link the service life cycle to the hardware device /dev/radio/ft99a1-00. I don't know why, but
|
||||
# you can't specify the file location of the device here. You have to do this syntax. Note that
|
||||
@@ -25,13 +25,12 @@ ExecStartPre=/bin/sleep 5
|
||||
#
|
||||
# This is automatic. All you have to do is switch the frequency on the 991a and this detects that and
|
||||
# stops/starts Direwolf with the matching packet configuration.
|
||||
ExecStart=/opt/busnet/direwolf/ft991a-monitor.sh
|
||||
#ExecStart=/opt/busnet/direwolf/ft991a_monitor.py
|
||||
ExecStart=/opt/argus/scripts/ft991a-monitor.sh
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
User=busnet
|
||||
Group=busnet
|
||||
User=argus
|
||||
Group=argus
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
# This file is managed by BusNet Ansible.
|
||||
# This file is managed by Ansible.
|
||||
#
|
||||
# This service starts rigctld when the Yeasu FT-991A radio USB is connected to this computer.
|
||||
# This uses port 4000
|
||||
@@ -23,8 +23,8 @@ ExecStartPre=/bin/sleep 4
|
||||
ExecStart=/usr/local/bin/rigctld -m 1035 -r /dev/radio/ft991a-00 -t 4000 -s 38400 --set-conf=data_bits=8, stop_bits=1, serial_parity=None, serial_handshake=None, dtr_state=OFF, rts_state=ON
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
User=busnet
|
||||
Group=busnet
|
||||
User=argus
|
||||
Group=argus
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,18 +0,0 @@
|
||||
# This file is managed by BusNet Ansible.
|
||||
#
|
||||
# ALSA pseudo-devices for Yaesu FT-991a
|
||||
# These bridge ALSA applications to PulseAudio devices
|
||||
#
|
||||
|
||||
# This is an ALSO psuedo device that actually connects to PulseAudio! This way things that need
|
||||
# ALSA (like Direwolf) can use PulseAudio and won't hog up the device.
|
||||
pcm.ft991a-playback {
|
||||
type pulse
|
||||
device "alsa_output.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo"
|
||||
}
|
||||
|
||||
# Same for this
|
||||
pcm.ft991a-capture {
|
||||
type pulse
|
||||
device "alsa_input.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo"
|
||||
}
|
||||
@@ -1,26 +1,25 @@
|
||||
# This file is managed by BusNet Ansible
|
||||
#
|
||||
# This is the Direwolf configuration for connecting Direwolf to the Yaesu FT-991a radio when it is
|
||||
# plugged in via USB and tuned to an HF frequency.
|
||||
#
|
||||
# Note that only one direwolf will ever be running at the same time for this 991a radio, depending
|
||||
# on what frequency it is tuned to. See /opt/busnet/direwolf/ft991a_monitor.py
|
||||
# This file is managed by Ansible
|
||||
#
|
||||
# There us a udev rule which creates "/dev/radio/ft99a1-00" and "/dev/radio/ft991a-01" so that we
|
||||
# do not have to worry about what USB port or tty number is assigned when this radio is connected
|
||||
# to the computer.
|
||||
|
||||
# IF Direwolf uses the ALSA device directly, this would be the device name. However, we do not
|
||||
# use ALSA any more because only one device at a time can use the audio device this way, and when
|
||||
# Direwolf is running, it locks it.
|
||||
#ADEVICE plughw:CODEC,0
|
||||
# We create a custom ALSA sound card name of "ft991a" in our udev rules. Direwolf uses ALSA directly,
|
||||
# so this tells Direwolf to use the "ft991a" sound card, subdevice #0 (there is only 1 subdevice).
|
||||
#ADEVICE plughw:CARD=ft991a,DEV=0
|
||||
|
||||
# This are peusdo ALSA devices created by PulseAudio! PulseAudio controls the ALSA device and then
|
||||
# create this fake ALSA device that is actually connected directly to PulseAudio. This way Pulse
|
||||
# locks the ALSA device, but then Pulse allows many devices to use the FT991a sound card, even
|
||||
# over the network.
|
||||
# These are defined in /etc/asound.conf
|
||||
ADEVICE ft991a-capture ft991a-playback
|
||||
# These are defined in ~/.asoundrc
|
||||
ADEVICE ft991a_rx ft991a_tx
|
||||
|
||||
# PulseAudio detects the hardware rate of 44,100Khz. However, using that rate generates buffer
|
||||
# underruns and the audio is garbled. I set it at half the rate randomly and no more buffer underruns
|
||||
# I don't know the most optimal value to put here. I've also randomly used a rate of 32000 and that
|
||||
# also worked. Not sure what is better.
|
||||
ARATE 22500
|
||||
|
||||
# The custom udev rule makes this device available by name.
|
||||
PTT /dev/radio/ft991a-01 RTS
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
# This file is managed by BusNet Ansible
|
||||
# This file is managed by Ansible
|
||||
#
|
||||
# This is the Direwolf configuration for connecting Direwolf to the Yaesu FT-991a radio when it is
|
||||
# plugged in via USB and tuned to an UHF frequency.
|
||||
#
|
||||
# Note that only one direwolf will ever be running at the same time for this 991a radio, depending
|
||||
# on what frequency it is tuned to. See /opt/busnet/direwolf/ft991a_monitor.py
|
||||
#
|
||||
# There us a udev rule which creates "/dev/radio/ft99a1-00" and "/dev/radio/ft991a-01" so that we
|
||||
# do not have to worry about what USB port or tty number is assigned when this radio is connected
|
||||
# to the computer.
|
||||
|
||||
# IF Direwolf uses the ALSA device directly, this would be the device name. However, we do not
|
||||
# use ALSA any more because only one device at a time can use the audio device this way, and when
|
||||
# Direwolf is running, it locks it.
|
||||
#ADEVICE plughw:CODEC,0
|
||||
# We create a custom ALSA sound card name of "ft991a" in our udev rules. Direwolf uses ALSA directly,
|
||||
# so this tells Direwolf to use the "ft991a" sound card, subdevice #0 (there is only 1 subdevice).
|
||||
#ADEVICE plughw:CARD=ft991a,DEV=0
|
||||
|
||||
# This are peusdo ALSA devices created by PulseAudio! PulseAudio controls the ALSA device and then
|
||||
# create this fake ALSA device that is actually connected directly to PulseAudio. This way Pulse
|
||||
# locks the ALSA device, but then Pulse allows many devices to use the FT991a sound card, even
|
||||
# over the network.
|
||||
# These are defined in /etc/asound.conf
|
||||
ADEVICE ft991a-capture ft991a-playback
|
||||
# These are defined in ~/.asoundrc
|
||||
ADEVICE ft991a_rx ft991a_tx
|
||||
|
||||
# PulseAudio detects the hardware rate of 44,100Khz. However, using that rate generates buffer
|
||||
# underruns and the audio is garbled. I set it at half the rate randomly and no more buffer underruns
|
||||
# I don't know the most optimal value to put here. I've also randomly used a rate of 32000 and that
|
||||
# also worked. Not sure what is better.
|
||||
ARATE 22500
|
||||
|
||||
# The custom udev rule makes this device available by name.
|
||||
PTT /dev/radio/ft991a-01 RTS
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
# This file is managed by BusNet Ansible
|
||||
# This file is managed by Ansible
|
||||
#
|
||||
# This is the Direwolf configuration for connecting Direwolf to the Yaesu FT-991a radio when it is
|
||||
# plugged in via USB and tuned to an VHF frequency.
|
||||
#
|
||||
# Note that only one direwolf will ever be running at the same time for this 991a radio, depending
|
||||
# on what frequency it is tuned to. See /opt/busnet/direwolf/ft991a_monitor.py
|
||||
#
|
||||
# There us a udev rule which creates "/dev/radio/ft99a1-00" and "/dev/radio/ft991a-01" so that we
|
||||
# do not have to worry about what USB port or tty number is assigned when this radio is connected
|
||||
# to the computer.
|
||||
|
||||
# IF Direwolf uses the ALSA device directly, this would be the device name. However, we do not
|
||||
# use ALSA any more because only one device at a time can use the audio device this way, and when
|
||||
# Direwolf is running, it locks it.
|
||||
#ADEVICE plughw:CODEC,0
|
||||
# We create a custom ALSA sound card name of "ft991a" in our udev rules. Direwolf uses ALSA directly,
|
||||
# so this tells Direwolf to use the "ft991a" sound card, subdevice #0 (there is only 1 subdevice).
|
||||
#ADEVICE plughw:CARD=ft991a,DEV=0
|
||||
|
||||
# This are peusdo ALSA devices created by PulseAudio! PulseAudio controls the ALSA device and then
|
||||
# create this fake ALSA device that is actually connected directly to PulseAudio. This way Pulse
|
||||
# locks the ALSA device, but then Pulse allows many devices to use the FT991a sound card, even
|
||||
# over the network.
|
||||
# These are defined in /etc/asound.conf
|
||||
ADEVICE ft991a-capture ft991a-playback
|
||||
# These are defined in ~/.asoundrc
|
||||
ADEVICE ft991a_rx ft991a_tx
|
||||
|
||||
# PulseAudio detects the hardware rate of 44,100Khz. However, using that rate generates buffer
|
||||
# underruns and the audio is garbled. I set it at half the rate randomly and no more buffer underruns
|
||||
# I don't know the most optimal value to put here. I've also randomly used a rate of 32000 and that
|
||||
# also worked. Not sure what is better.
|
||||
ARATE 22500
|
||||
|
||||
# The custom udev rule makes this device available by name.
|
||||
PTT /dev/radio/ft991a-01 RTS
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
# | Radio | ----- via USB socket on rear of radio.
|
||||
# +-------+
|
||||
# |
|
||||
# | USB
|
||||
# | USB
|
||||
# |
|
||||
# +----|----------------------------------------------------------------------------+
|
||||
# | | This is your computer. The things in here are virtual components. |
|
||||
@@ -95,11 +95,11 @@ WAITING_FOR_RADIO=false
|
||||
poll_rigctld()
|
||||
{
|
||||
local RESP=$(echo "+\\get_freq" | nc -w 2 $RIGCTLD_HOST $RIGCTLD_PORT 2>/dev/null)
|
||||
|
||||
|
||||
if [ -n "$RESP" ]; then
|
||||
# Parse frequency from response
|
||||
local FREQ=$(echo "$RESP" | grep "Frequency:" | awk '{print $2}')
|
||||
|
||||
|
||||
if [ -n "$FREQ" ] && [ "$FREQ" -eq "$FREQ" ] 2>/dev/null; then
|
||||
# Determine band
|
||||
if [ $FREQ -ge $HF_MIN ] && [ $FREQ -le $HF_MAX ]; then
|
||||
@@ -117,7 +117,7 @@ poll_rigctld()
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
echo "ERROR"
|
||||
return 1
|
||||
}
|
||||
@@ -155,20 +155,20 @@ cleanup_stack()
|
||||
# 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
|
||||
done
|
||||
fi
|
||||
|
||||
echo "FT991a AX.25 ${CUR_BAND} stack is now shut down."
|
||||
@@ -183,7 +183,7 @@ start_stack()
|
||||
{
|
||||
local BAND=$1
|
||||
local CONFIG=""
|
||||
|
||||
|
||||
case $BAND in
|
||||
HF) CONFIG="$CONFIG_HF" ;;
|
||||
VHF) CONFIG="$CONFIG_VHF" ;;
|
||||
@@ -193,9 +193,9 @@ start_stack()
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
echo "Starting $BAND stack..."
|
||||
|
||||
|
||||
# Start Direwolf in background
|
||||
$DIREWOLF_PATH -t 0 -X 1 -c "$CONFIG" &
|
||||
DIREWOLF_PID=$!
|
||||
@@ -209,7 +209,7 @@ start_stack()
|
||||
return 1
|
||||
fi
|
||||
echo "Direwolf started (PID: $DIREWOLF_PID)"
|
||||
|
||||
|
||||
# Start socat PTY bridge
|
||||
sleep 3
|
||||
sudo socat PTY,raw,echo=0,link=$TNC_DEV TCP4:127.0.0.1:$KISS_TCP_PORT &
|
||||
@@ -220,21 +220,21 @@ start_stack()
|
||||
return 1
|
||||
fi
|
||||
echo "socat started (PID: $SOCAT_PID)"
|
||||
|
||||
|
||||
# Wait for PTY device to exist
|
||||
local WAIT_COUNT=0
|
||||
while [ ! -L $TNC_DEV ] && [ $WAIT_COUNT -lt 10 ]; do
|
||||
sleep 0.5
|
||||
((WAIT_COUNT++))
|
||||
done
|
||||
|
||||
|
||||
if [ ! -L $TNC_DEV ]; then
|
||||
echo "PTY device $TNC_DEV not created" >&2
|
||||
cleanup_stack
|
||||
return 1
|
||||
fi
|
||||
echo "socat started (PID: $SOCAT_PID)"
|
||||
|
||||
|
||||
# Kissattach connects the PTY device created by socat to the kernel.
|
||||
echo "Running kissattach..."
|
||||
sudo kissattach $TNC_DEV $AX25_PORT_NAME
|
||||
@@ -244,7 +244,7 @@ start_stack()
|
||||
return 1
|
||||
fi
|
||||
echo "kissattach completed"
|
||||
|
||||
|
||||
# Set kissparams depending on what band we're operating on.
|
||||
echo "Setting kissparms..."
|
||||
case $BAND in
|
||||
@@ -279,7 +279,7 @@ start_stack()
|
||||
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-enabled --quiet netromd.service; then
|
||||
if ! sudo systemctl is-active --quiet netromd.service; then
|
||||
echo "Re-starting netromd..."
|
||||
sudo systemctl start netromd.service
|
||||
@@ -332,7 +332,7 @@ fi
|
||||
|
||||
while true; do
|
||||
TARGET_BAND=$(poll_rigctld)
|
||||
|
||||
|
||||
if [ "$WAITING_FOR_RADIO" = true ]; then
|
||||
# In waiting mode - check if radio is back online
|
||||
if [ "$TARGET_BAND" != "ERROR" ]; then
|
||||
@@ -344,12 +344,12 @@ while true; do
|
||||
sleep $POLL_INTERVAL
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
# Normal operation mode
|
||||
if [ "$TARGET_BAND" == "ERROR" ]; then
|
||||
((CONSECUTIVE_ERRORS++))
|
||||
echo "Radio unreachable ($CONSECUTIVE_ERRORS/$MAX_CONSECUTIVE_ERRORS)"
|
||||
|
||||
|
||||
if [ $CONSECUTIVE_ERRORS -ge $MAX_CONSECUTIVE_ERRORS ]; then
|
||||
echo "Radio offline. Waiting for radio to be reachable again."
|
||||
cleanup_stack
|
||||
@@ -359,7 +359,7 @@ while true; do
|
||||
else
|
||||
# Reset error counter on any successful poll
|
||||
CONSECUTIVE_ERRORS=0
|
||||
|
||||
|
||||
# Only act on valid digital bands (HF, VHF, UHF)
|
||||
if [[ "$TARGET_BAND" =~ ^(HF|VHF|UHF)$ ]]; then
|
||||
# Band switch needed?
|
||||
@@ -368,7 +368,7 @@ while true; do
|
||||
echo "Band change detected: $CUR_BAND -> $TARGET_BAND"
|
||||
cleanup_stack
|
||||
fi
|
||||
|
||||
|
||||
start_stack "$TARGET_BAND"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "FATAL: Failed to start FT991a AX.25 stack for $TARGET_BAND" >&2
|
||||
@@ -380,7 +380,7 @@ while true; do
|
||||
: # No-op
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Poll interval sleep
|
||||
sleep $POLL_INTERVAL
|
||||
done
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# @author Craig McDaniel using Google Gemini LLM
|
||||
#
|
||||
#
|
||||
# *** THIS IS NOT USED ***
|
||||
# This was an early version of the monitor script. It's been rewritten in bash. I might just
|
||||
# delete this.
|
||||
#
|
||||
#
|
||||
# This script polls the Yeasu FT-991a by connecting to a running rigctld daemon and asking that
|
||||
# daemon what the current radio's frequency is. If the radio is in any HF frequency, it makes
|
||||
# sure Direwolf is running with a HF AX.25 configuration at 300 baud. If a VHF or UHF frequency
|
||||
# is detected, it restarts Direwolf with a configuration suitable for that band
|
||||
#
|
||||
# * Note that ANY HF frequency will trigger a Direwolf restart with HF config.
|
||||
#
|
||||
# * For VHF anf UHF, specific ranges are specified as to only run Direwolf when the radio is
|
||||
# detected to be in the accepted packet frequencies of each band. The reason is to stop the
|
||||
# start and restart of Direwolf when the radio is in scan mode, and it constantly scans both
|
||||
# VHF and UHF frequencies. This will randomly trigger a reload of Direwolf over and over
|
||||
# when the 5 second poll randomly returns a VHF or UHF frequency. I think scanning data freqs
|
||||
# are not useful, and a operator would not normally scan those. But they will scan simplex and
|
||||
# repeater output frequencies, but those aren't for data, so no need to restart Direwolf.
|
||||
#
|
||||
# * If this script detects that the radio is on an out of range frequency, it does nothing. If
|
||||
# Direwolf is already running, it leaves it alone. As soon as it detects that the radio is within
|
||||
# range of a HF-UHF packet frequency, it makes sure Direwolf is running with the correct config.
|
||||
#
|
||||
|
||||
import socket
|
||||
import subprocess
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
import signal
|
||||
from typing import Optional, Dict
|
||||
|
||||
# --- Configuration (Centralized) ---
|
||||
DIREWOLF_PATH = '/usr/local/bin/direwolf'
|
||||
|
||||
CONFIG = {
|
||||
'RIGCTLD_HOST': 'localhost',
|
||||
'RIGCTLD_PORT': 4000,
|
||||
'RIGCTLD_TIMEOUT': 5.0,
|
||||
'POLL_INTERVAL': 5.0,
|
||||
|
||||
# !!! CONFIGURATION FILES !!!
|
||||
'CONFIG_FILES': {
|
||||
'HF': '/opt/busnet/direwolf/config/ft991a-hf.conf',
|
||||
'VHF': '/opt/busnet/direwolf/config/ft991a-vhf.conf',
|
||||
'UHF': '/opt/busnet/direwolf/config/ft991a-uhf.conf',
|
||||
},
|
||||
|
||||
# --- Narrowed Frequency Windows (in Hz) ---
|
||||
# Edit these to the exact ranges you use for Digital modes.
|
||||
# Frequencies outside these ranges will cause Dire Wolf to stop.
|
||||
'HF_MIN_FREQ': 1_800_000,
|
||||
'HF_MAX_FREQ': 30_000_000,
|
||||
|
||||
'VHF_MIN_FREQ': 144_390_000, # This captures APRS at 143390
|
||||
'VHF_MAX_FREQ': 145_100_000, # and various commonly used packet frequencies between 145000 - 145100
|
||||
|
||||
'UHF_MIN_FREQ': 432_000_000,
|
||||
'UHF_MAX_FREQ': 433_000_000,
|
||||
|
||||
'DIREWOLF_ARGS': ['-t', '0', '-X', '1'],
|
||||
}
|
||||
|
||||
|
||||
class ModeSwitcherDaemon:
|
||||
def __init__(self, config: Dict):
|
||||
self.rigctld_host = config['RIGCTLD_HOST']
|
||||
self.rigctld_port = config['RIGCTLD_PORT']
|
||||
self.rigctld_timeout = config['RIGCTLD_TIMEOUT']
|
||||
self.poll_interval = config['POLL_INTERVAL']
|
||||
self.config_files = config['CONFIG_FILES']
|
||||
self.direwolf_path = DIREWOLF_PATH
|
||||
self.direwolf_args = config['DIREWOLF_ARGS']
|
||||
|
||||
self.direwolf_process: Optional[subprocess.Popen] = None
|
||||
self.current_band: Optional[str] = None
|
||||
self._shutdown_flag = False
|
||||
|
||||
# Ranges
|
||||
self.hf_min = config['HF_MIN_FREQ']
|
||||
self.hf_max = config['HF_MAX_FREQ']
|
||||
self.vhf_min = config['VHF_MIN_FREQ']
|
||||
self.vhf_max = config['VHF_MAX_FREQ']
|
||||
self.uhf_min = config['UHF_MIN_FREQ']
|
||||
self.uhf_max = config['UHF_MAX_FREQ']
|
||||
|
||||
def _get_frequency_and_band(self) -> Optional[str]:
|
||||
temp_sock: Optional[socket.socket] = None
|
||||
try:
|
||||
temp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
temp_sock.settimeout(self.rigctld_timeout)
|
||||
temp_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
temp_sock.connect((self.rigctld_host, self.rigctld_port))
|
||||
|
||||
temp_sock.sendall(b'+\\get_freq\n')
|
||||
temp_sock.shutdown(socket.SHUT_WR) # Send EOF signal
|
||||
|
||||
full_response = temp_sock.recv(4096).decode('utf-8')
|
||||
temp_sock.close()
|
||||
|
||||
lines = full_response.strip().split('\n')
|
||||
frequency_str = None
|
||||
|
||||
for line in lines:
|
||||
if line.startswith('Frequency:'):
|
||||
frequency_str = line.split(':')[1].strip()
|
||||
break
|
||||
|
||||
if frequency_str is None or not frequency_str.isdigit():
|
||||
return None
|
||||
|
||||
frequency = int(frequency_str)
|
||||
|
||||
# Use strict bounded windows to avoid voice scan triggers
|
||||
if self.hf_min <= frequency <= self.hf_max:
|
||||
return 'HF'
|
||||
elif self.vhf_min <= frequency <= self.vhf_max:
|
||||
return 'VHF'
|
||||
elif self.uhf_min <= frequency <= self.uhf_max:
|
||||
return 'UHF'
|
||||
else:
|
||||
return 'UNKNOWN' # Not in a managed digital window
|
||||
|
||||
except Exception as e:
|
||||
print(f"ERROR: rigctld communication error: {e}", file=sys.stderr)
|
||||
return None
|
||||
|
||||
def _kill_direwolf_process(self):
|
||||
if self.direwolf_process:
|
||||
print(f"INFO: Terminating Dire Wolf on {self.current_band}...")
|
||||
try:
|
||||
self.direwolf_process.terminate()
|
||||
self.direwolf_process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
self.direwolf_process.kill()
|
||||
self.direwolf_process.wait()
|
||||
finally:
|
||||
self.direwolf_process = None
|
||||
self.current_band = None
|
||||
|
||||
def _run_direwolf(self, target_band: str):
|
||||
# Idempotency check: Already running on the right band?
|
||||
if self.direwolf_process and self.direwolf_process.poll() is None and self.current_band == target_band:
|
||||
return
|
||||
|
||||
# If running on the wrong band, kill it first
|
||||
if self.direwolf_process:
|
||||
print(f"INFO: Band changed. Switching from {self.current_band} to {target_band}.")
|
||||
self._kill_direwolf_process()
|
||||
|
||||
try:
|
||||
config_file = self.config_files[target_band]
|
||||
print(f"INFO: Launching Dire Wolf for {target_band}...")
|
||||
|
||||
command_args = [self.direwolf_path] + self.direwolf_args + ['-c', config_file]
|
||||
self.direwolf_process = subprocess.Popen(command_args)
|
||||
self.current_band = target_band
|
||||
|
||||
except Exception as e:
|
||||
print(f"FATAL: Failed to launch Dire Wolf: {e}", file=sys.stderr)
|
||||
|
||||
def handle_signal(self, signum, frame):
|
||||
self._shutdown_flag = True
|
||||
|
||||
def run(self):
|
||||
signal.signal(signal.SIGINT, self.handle_signal)
|
||||
signal.signal(signal.SIGTERM, self.handle_signal)
|
||||
|
||||
print("INFO: FT-991A Frequency Monitor Started.")
|
||||
|
||||
while not self._shutdown_flag:
|
||||
target_band = self._get_frequency_and_band()
|
||||
|
||||
# Change: Only act if we find a valid digital band.
|
||||
# If target_band is 'UNKNOWN' or None (comm error), we do absolutely nothing.
|
||||
if target_band in ['HF', 'VHF', 'UHF']:
|
||||
self._run_direwolf(target_band)
|
||||
|
||||
# Poll interval sleep
|
||||
for _ in range(int(self.poll_interval * 10)):
|
||||
if self._shutdown_flag: break
|
||||
time.sleep(0.1)
|
||||
|
||||
self._kill_direwolf_process()
|
||||
print("INFO: Monitor exited.")
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not os.path.exists(DIREWOLF_PATH):
|
||||
print(f"FATAL: Dire Wolf executable not found at {DIREWOLF_PATH}.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
daemon = ModeSwitcherDaemon(CONFIG)
|
||||
daemon.run()
|
||||
Reference in New Issue
Block a user