Files
ubuntu-based-kiosk/menus/addon_asterisk_intercom.sh
T
Claude 3eadcdb584 Migrate Asterisk Intercom, redesigned as SIP-extension-only; bump to v2.10.0
New menus/addon_asterisk_intercom.sh, wired into install.sh's Addons
menu. The legacy addon offered Client Only (Baresip SIP client), Server
Only, and Full (server + client), where Server/Full downloaded and ran
a third-party installer from a separate "Easy Asterisk" repository to
stand up a whole Asterisk PBX. That repository has since gone through a
major rework upstream, so this migration drops the PBX-install path
entirely: the addon now only installs Baresip and registers this kiosk
as a SIP extension against an Asterisk server the user already has
running elsewhere. It never installs or manages Asterisk itself. The
legacy script's own three-option version is untouched, same as every
other migrated menu.

Dropped the legacy client path's dependency on the Easy Asterisk repo's
GitHub API for version tracking - now reads the real installed baresip
package version via dpkg instead. Added an uninstall option, which the
legacy addon never had at all.

Bug fix found while testing: an unguarded `ver=$(baresip_installed_version)`
assignment crashed the whole session under set -e the first time status
was checked before Baresip was installed (dpkg-query legitimately fails
when the package isn't there). Guarded with `|| true`.

Full command-level stubbed test suite covering configure (manual/auto-
answer, TLS port bump, apt-install failure) and uninstall (keep/purge
config) for both fresh and already-configured states. Full 13-suite
regression + real end-to-end menu navigation via install.sh all pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VfsFSoRqfbRG7XAg5RoE7e
2026-08-19 02:28:05 +00:00

280 lines
10 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
################################################################################
# menus/addon_asterisk_intercom.sh - "Asterisk Intercom" addon: connect the
# kiosk as a SIP extension to an *existing* Asterisk server.
#
# The legacy addon offered three options: Client Only (a Baresip SIP
# client - what this file is), Server Only, and Full (server + client).
# Server/Full downloaded and ran a third-party installer from a separate
# "Easy Asterisk" repository to stand up a whole Asterisk PBX. That
# repository has since gone through a major rework upstream, so wiring a
# full PBX install through it here no longer makes sense to maintain -
# and most kiosk deployments don't need this device to *be* the PBX
# anyway. This addon now does only the client/endpoint piece: install
# Baresip and register it as one extension against an Asterisk server
# the user already has running somewhere else. It never installs or
# manages Asterisk itself.
#
# Two other things fixed while narrowing the scope:
# - The legacy client path tracked its own version by calling out to the
# (now-reworked) Easy Asterisk repo's GitHub API and stamping a
# "<repo-version>-client" string in a side file. That coupling is
# exactly what's being dropped, so version tracking now just reads the
# real installed `baresip` package version via dpkg - one less network
# dependency and one less thing to keep in sync with an external repo.
# - The legacy addon had no uninstall option for the client at all -
# added below.
#
# Real system state: apt package, a per-user config directory under
# $KIOSK_HOME, and a systemd --user unit for $KIOSK_USER (not a system
# service - Baresip needs the desktop session's PulseAudio/PipeWire
# socket). Every write goes through `sudo`/`sudo -u "$KIOSK_USER"`, all
# stubbed at the command level in tests - there's no real D-Bus user
# session to target in a test container regardless.
#
# Depends on: lib/menu.sh, lib/config.sh being sourced first.
################################################################################
BARESIP_CONFIG_DIR="${KIOSK_HOME}/.baresip"
BARESIP_USER_SERVICE_DIR="${KIOSK_HOME}/.config/systemd/user"
# Runs `systemctl --user ...` as $KIOSK_USER with the runtime dir/D-Bus
# address it needs to find that user's session. Always call from an
# `if`/`&&`/`||` context - see run_menu's own comment on why a bare call
# that can legitimately fail must never be a standalone statement.
baresip_systemctl_user() {
local kiosk_uid
kiosk_uid=$(id -u "$KIOSK_USER" 2>/dev/null) || return 1
sudo -u "$KIOSK_USER" \
XDG_RUNTIME_DIR="/run/user/${kiosk_uid}" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/${kiosk_uid}/bus" \
systemctl --user "$@"
}
baresip_installed_version() {
dpkg-query -W -f='${Version}' baresip 2>/dev/null || true
}
# "Installed" means both the package and a written account - a bare
# `apt install baresip` with no configured extension isn't something
# this menu should call done.
baresip_is_installed() {
command -v baresip &>/dev/null && [[ -f "$BARESIP_CONFIG_DIR/accounts" ]]
}
baresip_is_running() {
baresip_systemctl_user is-active --quiet baresip.service 2>/dev/null
}
addon_asterisk_intercom_status() {
if baresip_is_installed; then
local ver
ver=$(baresip_installed_version)
if baresip_is_running; then
echo "Asterisk Intercom: Installed (v${ver:-unknown}) - Running"
else
echo "Asterisk Intercom: Installed (v${ver:-unknown}) - Not running"
fi
if [[ -f "$BARESIP_CONFIG_DIR/accounts" ]]; then
local account
account=$(head -1 "$BARESIP_CONFIG_DIR/accounts" 2>/dev/null)
local extension="${account#<sip:}"
extension="${extension%%@*}"
[[ -n "$extension" ]] && echo " Extension: $extension"
fi
else
echo "Asterisk Intercom: Not installed"
fi
echo " Connects this kiosk as a SIP extension to an Asterisk server"
echo " you already have running elsewhere - it does not install or"
echo " manage Asterisk itself."
}
addon_asterisk_intercom_menu_builder() {
if baresip_is_installed; then
MENU_LABELS=("Reconfigure (new server/extension)" "Uninstall")
MENU_HANDLERS=(action_configure_asterisk_intercom action_uninstall_asterisk_intercom)
else
MENU_LABELS=("Connect to an Asterisk server")
MENU_HANDLERS=(action_configure_asterisk_intercom)
fi
}
addon_asterisk_intercom_menu() {
run_menu "ASTERISK INTERCOM (SIP EXTENSION)" addon_asterisk_intercom_menu_builder addon_asterisk_intercom_status
}
################################################################################
# Actions
################################################################################
action_configure_asterisk_intercom() {
echo
if baresip_is_installed; then
echo "Asterisk Intercom is already configured."
ask_yes_no "Reconfigure with a different server/extension?" "n" || { pause; return; }
fi
echo "Enter the details of the Asterisk server this kiosk should"
echo "register to as an extension (these must match what's already"
echo "configured on that server)."
echo
local server_ip=""
while [[ -z "$server_ip" ]]; do
server_ip=$(ask_text "Server IP or hostname" "")
[[ -z "$server_ip" ]] && log_error "Server address is required"
done
local server_port
server_port=$(ask_integer "Server port" 5060 1 65535)
local extension=""
while [[ -z "$extension" ]]; do
extension=$(ask_text "Extension number (e.g. 201)" "")
[[ -z "$extension" ]] && log_error "Extension is required"
done
local password=""
while [[ -z "$password" ]]; do
read -r -s -p "SIP password: " password
echo
[[ -z "$password" ]] && log_error "Password is required"
done
local answermode="manual"
if ask_yes_no "Auto-answer incoming calls (intercom mode)?" "n"; then
answermode="auto"
fi
local transport="udp"
local media_enc=""
if ask_yes_no "Use TLS encryption?" "n"; then
transport="tls"
media_enc=";mediaenc=srtp"
if [[ "$server_port" == "5060" ]]; then
server_port=5061
echo "Note: port changed to 5061 for TLS"
fi
fi
echo
echo "Configuration summary:"
echo " Server: ${server_ip}:${server_port}"
echo " Extension: ${extension}"
echo " Answer: $([[ "$answermode" == "auto" ]] && echo "Auto" || echo "Manual")"
echo " TLS: $([[ "$transport" == "tls" ]] && echo "Yes" || echo "No")"
echo
ask_yes_no "Proceed with installation?" "y" || { echo "Cancelled"; pause; return; }
echo
echo "Installing Baresip..."
if ! command -v baresip &>/dev/null; then
if ! sudo apt install -y baresip; then
log_error "Failed to install baresip package"
pause
return 1
fi
fi
sudo apt install -y pulseaudio-utils pipewire-pulse 2>/dev/null || true
sudo mkdir -p "$BARESIP_CONFIG_DIR"
sudo tee "$BARESIP_CONFIG_DIR/accounts" > /dev/null <<EOF
<sip:${extension}@${server_ip}:${server_port};transport=${transport}>;auth_pass=${password};answermode=${answermode}${media_enc}
EOF
if [[ ! -f "$BARESIP_CONFIG_DIR/config" ]]; then
sudo tee "$BARESIP_CONFIG_DIR/config" > /dev/null <<'BARESIPCONFIG'
# Baresip configuration for Asterisk Intercom
# Audio settings
audio_player pulse,default
audio_source pulse,default
audio_alert pulse,default
# Call settings
call_local_timeout 120
call_max_calls 4
# Network settings
net_interface
# SIP settings
sip_trans_bsize 128
sip_verify_server no
# Module loading
module pulse.so
module account.so
module contact.so
module menu.so
module stdio.so
module uuid.so
module debug_cmd.so
BARESIPCONFIG
fi
sudo chown -R "${KIOSK_USER}:${KIOSK_USER}" "$BARESIP_CONFIG_DIR"
sudo chmod 600 "$BARESIP_CONFIG_DIR/accounts"
sudo mkdir -p "$BARESIP_USER_SERVICE_DIR"
sudo tee "$BARESIP_USER_SERVICE_DIR/baresip.service" > /dev/null <<'BARESIPUNIT'
[Unit]
Description=Baresip SIP Client
After=pipewire.service pipewire-pulse.service
Wants=pipewire-pulse.service
[Service]
Type=simple
ExecStart=/usr/bin/baresip -f %h/.baresip
Restart=always
RestartSec=5
Environment=PULSE_SERVER=unix:/run/user/%U/pulse/native
[Install]
WantedBy=default.target
BARESIPUNIT
sudo chown -R "${KIOSK_USER}:${KIOSK_USER}" "${KIOSK_HOME}/.config"
if baresip_systemctl_user daemon-reload 2>/dev/null && \
baresip_systemctl_user enable baresip.service 2>/dev/null && \
baresip_systemctl_user start baresip.service 2>/dev/null; then
log_success "Baresip service enabled and started"
else
log_warning "Baresip files written, but enabling/starting the user service failed - it will start automatically on next login. Check: systemctl --user status baresip"
fi
echo
log_success "Asterisk Intercom configured"
echo " Config dir: ${BARESIP_CONFIG_DIR}"
echo " Server: ${server_ip}:${server_port}"
echo " Extension: ${extension}"
echo
echo "Management commands (as $KIOSK_USER):"
echo " Check status: systemctl --user status baresip"
echo " Restart: systemctl --user restart baresip"
echo " View logs: journalctl --user -u baresip -f"
pause
}
action_uninstall_asterisk_intercom() {
echo
ask_yes_no "Remove Asterisk Intercom (Baresip)?" "n" || { echo "Cancelled"; pause; return; }
baresip_systemctl_user stop baresip.service 2>/dev/null || true
baresip_systemctl_user disable baresip.service 2>/dev/null || true
sudo rm -f "$BARESIP_USER_SERVICE_DIR/baresip.service"
sudo apt remove -y baresip 2>/dev/null || true
if ask_yes_no "Remove saved SIP configuration too?" "n"; then
sudo rm -rf "$BARESIP_CONFIG_DIR"
log_success "Asterisk Intercom removed (configuration deleted)"
else
log_success "Asterisk Intercom removed (configuration preserved)"
fi
pause
}