Skip to content

Software Guide

Nikogenia edited this page Mar 27, 2025 · 72 revisions

This is a big collection of various guides for different software operations. Use the links below to navigate!

Mission Control Console

This is a custom CLI tool specialized to monitor and control various aspects of the mission. These include live and video webcam configuration, stream overlay settings, countdown management and system execution state ...

Setup

  • make sure Python and Git are installed on your system
  • if no repository instance is available, clone from GitHub
    git clone https://github.com/BOGYLI/SpaceBalloon.git
  • change your working directory to the console folder of the repository
    cd SpaceBalloon/console
  • install the required packages
    pip install -r requirements.txt

Open

  • change your working directory to the console folder of the repository
    cd SpaceBalloon/console
  • open the console with (optional flags below)
    python main.py
  • enter the password

Offline Mode (Optional)

Can be used in the Space Balloon WiFi network to connect directly to the Raspberry Pi and APRS receiver.

  • use the command line flag -o or --offline for the python command
  • enter the password

Custom Mode (Optional)

Asks for every configurable option.

  • use the command line flag -c or --custom for the python command
  • follow the login options

Upload

Commands

Command Description
h Show help
q Quit
l[x] Livestream camera x
l Stop camera livestream
v[xy] Save video file for camera x, y
v Stop saving video file
pb Go back a phase
pn Go to next phase
s Toggle sensor data display
sc aprs Change connection source to APRS
sc wifi Change connection source to WiFi
sh gps Change height source to GPS altitude
sh climate Change height source to climate pressure
ts Select title and subtitle popup from configuration list
tc [title];[subtitle] Set title and subtitle popup to custom text
th Hide title and subtitle popup
r reboot system Reboot full Raspberry Pi system
r restart [service] Restart a systemd service
r start [service] Start a systemd service
r stop [service] Stop a systemd service
c[seconds] Set countdown to seconds
c [month];[day];[hour];[minute];[second] Set countdown to date and time
cs[seconds] Set stream countdown to seconds
cs [month];[day];[hour];[minute];[second] Set stream countdown to date and time

Audio

Usage

Setup

  • install the latest version of OBS Studio on the Windows 11 machine
  • download the OBS profile and scene collection Space_Balloon_Audio
  • import these via the options in the menu bar
  • open settings
    • go to the Stream tab
    • replace the second slot in the streamid with the desired stream path
      • mission control publish:audiomc:maker:#PASSWORD
      • launch field publish:audiosp:maker:#PASSWORD
      • radio publish:audioradio:maker:#PASSWORD
    • visit the Audio tab
      • make sure no inputs are configured as defaults
    • click Okay to exit the settings

APRS Receiver

Raspberry Pi

Usage guides are coming first for ease of discovery, the setup guide is following after.

Usage

  • there should be a Raspberry Pi OS Lite (64-bit) running
  • default user is maker
  • SSH access
  • the sp command does 2 things
    • change directory to the /home/maker/SpaceBalloon repository
    • execute the tool script at tools/name.sh with sudo if an argument is provided

Tool scripts are explained in the following sections.

Service Execution

  • start all services
    sp start
  • start a specific service (replace #SERVICE with the service name)
    sp start #SERVICE
  • stop all services
    sp stop
  • stop a specific service (replace #SERVICE with the service name)
    sp stop #SERVICE
  • restart all services
    sp restart
  • restart a specific service (replace #SERVICE with the service name)
    sp restart #SERVICE

Note that the prefix balloon- and suffix .service are added automatically!

Service Autostart

  • enable autostart for all services
    sp enable
  • enable autostart for a specific service (replace #SERVICE with the service name)
    sp enable #SERVICE
  • disable autostart for all services
    sp disable
  • disable autostart for a specific service (replace #SERVICE with the service name)
    sp disable #SERVICE

Note that the prefix balloon- and suffix .service are added automatically!

Environment

  • sp setup handles the following actions
    • creation of the Python virtual environment
    • installation of required packages
    • removal of old service files
    • registration of new service files
    • reloading systemd
    • service autostart
    • creation of the configuration file
  • configuration in config.yml is required afterwards (more details here)
  • the next step would be data storage initialization
  • should you change your mind sp uninstall does almost the opposite
    • removal of service files
    • reloading systemd
    • deletion of the Python virtual environment
    • deletion of the configuration file
    • deletion of the data storage

WARNING: BE AWARE OF WHAT YOU ARE DOING AND READ EVERYTHING CAREFULLY BEFORE COMMAND EXECUTION!

Data Storage

  • all data is stored in the data directory
  • sensor data is written to CSV files in sensor
  • photos and videos are available in video and the individual camera folder like cam0
  • to prepare this structure use
    sp reset
  • existing data will be all removed on reset making this a destructive action

WARNING: BE AWARE OF WHAT YOU ARE DOING AND READ EVERYTHING CAREFULLY BEFORE COMMAND EXECUTION!

Debug Utilities

  • view the latest systemd logs of a service (replace #SERVICE with the service name)
    splog #SERVICE
  • make it follow on updates (replace #SERVICE with the service name)
    splogf #SERVICE
  • go through the logs of all services one by one sp logall
  • to debug power delivery check all power rails of the Raspberry Pi using
    vcgencmd pmic_read_adc
  • I/O related system logs can be viewed with
    dmesg
  • if you have to check global logs of the whole system use \
    • sudo journalctl -b 0 for everything since this boot
    • sudo journalctl -e -b -1 for everything until last shutdown
    • add | grep #KEYWORD to filter for specific keywords
    • the option -k filters for kernel logs only

Note that the prefix balloon- and suffix .service are added automatically!

Backup

Method 1: USB drive (quite fast, recommended)

  • make sure you have physical access to the hardware
  • have an storage device formatted as exFAT prepared
  • start backup procedure
    sp backup
  • follow the instructions

Method 2: SSH over WiFi (very slow, only use if necessary)

  • open a terminal on a Windows machine connected to the network
  • make sure SSH access is possible
  • navigate to the repository and into the tools folder
  • start backup procedure
    backup.bat
  • follow the instructions

Configuration

There are a few things that can be configured through the config.yml file. To edit please use

  • sp
    to make sure you are in the repository directory
  • sudo nvim config.yml
    or
    sudo nano config.yml
    to open your preferred text editor.

Climate

sea_level_pressure: 1013.25
  • this value needs to be adjusted a few hours before launch
  • open this map
  • search for your location and read the current pressure conditions
  • set the sea level pressure in hPa (default value is 1013.25)

Sensor I2C Bus

bus:
  adc: 7
  co2: 5
  gps: 4
  magnet: 6
  • these are the I2C bus IDs of the sensors
  • they need to match the configuration in the /boot/firmware/config.txt available here
  • there is usually no need to change this

Intervals and Timeouts

interval:
  adc: 1
  climate: 1
  co2: 1
  magnet: 1
  spectral: 1
  system: 1
  • readout intervals in seconds for the sensors
  photo_offset: 4
  photo_delay: 20
  • the photo delay specifies the webcam photo interval in seconds
  • meanwhile the offset gets multiplied by the camera ID and added to a timing alignment grid in seconds
  • example with photo_offset: 4 and photo_delay: 20
    • webcam 0: now - (now % 20) + (0 * 4)
    • webcam 1: now - (now % 20) + (1 * 4)
    • webcam 2: now - (now % 20) + (2 * 4)
  dm_debug: 10
  dm_aprs: 60
  dm_influx: 3
  cm_debug: 10
  cm_services: 3
  cm_mode: 10
  • the debug intervals specify state logging for the data manager and camera manager in seconds
  • data manager aprs represents packet sending in seconds
  • data manager influx stands for measurement upload to database in seconds
  • camera manager services is the rate at which service and uptime monitoring is updated in seconds
  • camera manager mode sets management schedules for offline and pop mode
  ping_fail: 30
  cam_cycle: 120
  live_mode_stop: 30
  • how many seconds pings need to fail for switching to offline mode
  • cycle cameras in offline and pop mode every so many seconds
  • delay webcam livestream stop for an amount of seconds to give new streams some time to intialize

Webcam Path ID

webcams:
  0: "usb-xhci-hcd.1-2"
  1: "usb-xhci-hcd.0-1.2"
  2: "usb-xhci-hcd.0-1.3"
  3: "usb-xhci-hcd.1-1.4"
  4: "usb-xhci-hcd.1-1.3"
  • these values depend on your webcam USB cable management
  • list all webcams
    v4l2-ctl --list-devices
  • copy the USB path IDs from the parentheses
  • assign them to the webcams (this isn't the device index, but the module index)
  • this is necessary because of regularly changing camera device indices

Offline and Pop Mode

mode:
  offline_auto: true
  offline_ping: "192.168.25.2"
  • automatic switching to offline mode can be toggled on and off
  • the offline ping specifies the hostname to ping with ICMP to determine connection status
  pop_auto: true
  pop_pressure: 50
  pop_altitude: 25000
  • automatic switching to pop mode can be toggled on and off
  • the maximum pressure for pop mode in hPa
  • the minimum altitude for pop mode in meters

InfluxDB

influx:
  url: "https://influx.balloon.nikogenia.de"
  org: "makerspace"
  bucket: "balloon"
  token: ""
  • access information for the InfluxDB database

Stream

stream:
  url: "srt://server.balloon.nikogenia.de:8890?streamid=publish:#PATH:#USERNAME:#PASSWORD&pkt_size=1316"
  username: "maker"
  password: ""
  • stream URL for the SRT stream to the media server
  • username and password get replaced at the placeholders

APRS

aprs:
  device: "usb-Silicon_Labs_CP2102N_USB_to_UART_Bridge_Controller_02e63ec96457ed11b7bb50ca5720eef3-if00-port0"
  src: "DN5WA-2"
  dst: "APRS-0"
  • device is used to specify the USB path ID of the PicoAPRS connected
  • use can list all device and pick the right one with
    ls -l /dev/serial/by-id/
  • src stands for the source callsign for APRS packets
  • dst stands for the destination callsign for APRS packets

Storage Box

storage:
  sensor:
    default:
      path: "./data/sensor"
  video:
    path: "./data/video"
    backups: []
  • these options are legacy and shouldn't be changed due to unfinished implementation
  remote: "hetzner:System/photo"
  • remote path with rclone remote prefix for storage box upload location
  • do not use a / at the root position

Setup

The following steps are useful to make a full production instance of the software on board.

Flashing

  • use an external computer and insert the MicroSD card
  • start Raspberry Pi Imager, select model Raspberry Pi 5, operating system Raspberry Pi OS Lite (64-bit) and your MicroSD card
  • change your settings when prompted
    • hostname:
      spaceballoon
    • username:
      maker
    • password:
      ********
    • if you won't be able to access the console directly, configure a WiFi connection first
    • timezone:
      Europe/Berlin
    • keyboard layout:
      de
  • activate SSH access in the tab Services
  • save settings and start flash
  • remove MicroSD card when finished and insert into your Raspberry Pi

Network

  • power on system
  • login to console directly or via SSH
  • open Network Manager TUI using
    sudo nmtui
    • select Edit a connection and edit Wired connection
    • profile name:
      MikroTik
    • IPv4 configuration:
      Manual
      • addresses:
        192.168.25.4
      • gateway:
        192.168.25.1
      • DNS servers:
        1.1.1.1
        8.8.8.8
    • save connection via OK
    • optionally add a few WiFi hotspots as a backup recovery method
    • go back and use Activate a connection to make sure the ethernet connection is active
  • quit menu and verify your network setup
    ifconfig

Code and Dependencies

  • add package repositories
    curl -s https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh | sudo bash
  • install basic packages
    sudo apt install git neovim python3-dev wireguard ffmpeg ntp rclone speedtest i2c-tools
  • update packages
    sudo apt update && sudo apt upgrade
  • clone repository with
    git clone https://github.com/BOGYLI/SpaceBalloon.git
  • add the following bash alias configuration to the end of /etc/bash.bashrc
splog() {
    sudo journalctl -o cat -e -u balloon-$1.service
}

splogf() {
    sudo journalctl -o cat -f -u balloon-$1.service
}

sp() {
    cd /home/maker/SpaceBalloon
    if [ -n "$1" ]; then
        scriptname="$1"
        shift
        sudo tools/$scriptname.sh $@
    fi
}
  • setup rclone and configure a remote called hetzner for the storage box
    sudo rclone config

Interfaces

  • append panic=10 usbcore.autosuspend=-1 to /boot/firmware/cmdline.txt to activate kernel crash recovery
  • make sure I2C is enabled by uncommenting dtparam=i2c_arm=on
  • append the following lines to /boot/firmware/config.txt to activate software I2C
dtoverlay=i2c-gpio,bus=7,i2c_gpio_sda=8,i2c_gpio_scl=7
dtoverlay=i2c-gpio,bus=6,i2c_gpio_sda=12,i2c_gpio_scl=13
dtoverlay=i2c-gpio,bus=5,i2c_gpio_sda=22,i2c_gpio_scl=23
dtoverlay=i2c-gpio,bus=4,i2c_gpio_sda=5,i2c_gpio_scl=6

dtparam=uart0=on

usb_max_current_enable=1
  • edit the bootloader with sudo rpi-eeprom-config --edit by adding the line PSU_MAX_CURRENT=5000
  • open the Raspberry Pi configuration
    sudo raspi-config
    • navigate to Interface Options > I2C
    • select YES to enable
    • quit the menu
  • write the following VPN configuration to /etc/wireguard/wg0.conf (replace #KEY1 and #KEY2 accordingly)
[Interface]
PrivateKey = #KEY1
Address = 10.25.1.2/24

[Peer]
PublicKey = #KEY2
AllowedIPs = 10.25.1.0/24,10.25.0.0/24
Endpoint = server.balloon.nikogenia.de:51820
PersistentKeepalive = 25
  • enable the Wireguard service with the following systemctl commands
sudo systemctl enable [email protected]
sudo systemctl daemon-reload
sudo systemctl start wg-quick@wg0
sudo systemctl status wg-quick@wg0
  • restart the system
    sudo reboot

Space Balloon Software

  • this is a quick start summary
  • all operations in detail can be lookup up in the usage guide
  • setup environment
    sp setup
  • configure config.yml with secrets (more details here)
  • create data directories
    sp reset
  • start all services
    sp startall
  • everything should be running now

Server

Both the main and OBS server are rent in the Hetzner Cloud at the Hetzner datacenter in Nürnberg. The storage box with 1 TB capacity is hosted by Hetzner too.

Storage Box

Main Server

Usage

System Setup

First Steps

  • change the root password with
    passwd
  • configure the keyboard layout
    dpkg-reconfigure keyboard-configuration
    • Generic 105-key PC
    • Other (Only, if German isn't shown)
    • German
    • Right Alt (AltGr)
    • Right Alt (AltGr)
  • update configuration with
    setupcon
  • set timezone by executing
    timedatectl set-timezone Europe/Berlin
  • update and install packages
apt update
apt upgrade
apt install wireguard rclone neovim
  • reboot system with
    reboot
  • verify login via Hetzner console is working

Wireguard

[Interface]
PrivateKey = #
Address = 10.25.1.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]  
PublicKey = #
AllowedIPs = 10.25.1.2/32
PersistentKeepalive = 25
  • run wireguard manually to test whether everything is running
    wg-quick up /etc/wireguard/wg0.conf
  • stop test execution
    wg-quick down /etc/wireguard/wg0.conf
  • enable wireguard service
systemctl enable [email protected]
systemctl daemon-reload
systemctl start wg-quick@wg0
systemctl status wg-quick@wg0

Docker

  • delete old packages
    for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
  • add GPG key and repository
apt update
apt install ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
  • install docker packages
    apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  • test docker installation with hello world image
    docker run hello-world
  • create virtual docker network for more flexibility
    docker network create --subnet 172.18.0.0/16 --gateway 172.18.0.1 -o "com.docker.network.bridge.name"="server" server

Crontab

  • execute crontab -e to open the editor and append the following tasks
0 0 * * * /root/influx/backup.sh
0 1 * * * /root/prometheus/backup.sh
  • check success by inspecting the result of
    crontab -l

Node Exporter

  • create and switch to directory
    mkdir node-exporter && cd ./node-exporter
  • search for the latest release on https://github.com/prometheus/node_exporter/releases
  • insert version, OS and architecture into command and execute it
    wget https://github.com/prometheus/node_exporter/releases/download/v<VERSION>/node_exporter-<VERSION>.<OS>-<ARCH>.tar.gz
  • extract and test (Ctrl-C to exit)
tar xvfz node_exporter-*.*-*.tar.gz
rm node_exporter-*.*-*.tar.gz
cd node_exporter-*.*-*
./node_exporter
  • insert path, version, OS, architecture and save the service configuration to /etc/systemd/system/node-exporter.service
[Unit]
Description=Node Exporter

[Service]
User=root
Group=root
ExecStart=/<PATH>/node-exporter/node_exporter-<VERSION>.<OS>-<ARCH>/node_exporter

[Install]
WantedBy=multi-user.target
  • enable, start and check the service
systemctl enable node-exporter
systemctl daemon-reload
systemctl start node-exporter
systemctl status node-exporter

Rclone

  • enter configuration menu
    rclone config
    • create new remote
      n
      • name:
        hetzner
      • type:
        sftp
      • host (in our case the following, use your own if reproducing):
        u421785.your-storagebox.de
      • user (in our case the following, use your own if reproducing):
        u421785
      • port:
        23
      • select yes for own password:
        y
      • enter your password and repeat
      • repeat enter key until you are back to the main menu
    • quit the configuration
      q
  • test the connection by asking for storage status rclone about hetzner:

Docker Setup

Dockge

Traefik

Prometheus

Influx

Grafana

MediaMTX

OBS Server