This commit is contained in:
Alexandre
2024-10-09 10:09:20 +02:00
committed by GitHub
parent 62716e4176
commit da52b55f27
14 changed files with 452 additions and 460 deletions

View File

@@ -6,20 +6,19 @@ set -e
# SET /CONFIG #
###############
echo " "
bashio::log.info "Ensuring the file structure is correct :"
bashio::log.info "Ensuring the file structure is correct:"
# Define structure
# Create default configuration files if not present
echo "... creating default files"
touch /config/include_species_list.txt # Should be null
touch /home/pi/BirdNET-Pi/scripts/thisrun.txt
for files in apprise.txt exclude_species_list.txt IdentifiedSoFar.txt disk_check_exclude.txt confirmed_species_list.txt blacklisted_images.txt whitelist_species_list.txt; do
if [ ! -f /config/"$files" ]; then
echo "" > /config/"$files"
DEFAULT_FILES=("apprise.txt" "exclude_species_list.txt" "IdentifiedSoFar.txt" "disk_check_exclude.txt" "confirmed_species_list.txt" "blacklisted_images.txt" "whitelist_species_list.txt")
for file in "${DEFAULT_FILES[@]}"; do
if [ ! -f "/config/$file" ]; then
echo "" > "/config/$file"
fi
done
touch /config/include_species_list.txt # Ensure this is always created
# Get BirdSongs folder locations
# Set BirdSongs folder location from configuration if specified
BIRDSONGS_FOLDER="/config/BirdSongs"
if bashio::config.has_value "BIRDSONGS_FOLDER"; then
BIRDSONGS_FOLDER_OPTION="$(bashio::config "BIRDSONGS_FOLDER")"
@@ -29,65 +28,61 @@ if bashio::config.has_value "BIRDSONGS_FOLDER"; then
if [ -d "$BIRDSONGS_FOLDER_OPTION" ] && [ "$(stat -c '%u:%g' "$BIRDSONGS_FOLDER_OPTION")" == "1000:1000" ]; then
BIRDSONGS_FOLDER="$BIRDSONGS_FOLDER_OPTION"
else
bashio::log.yellow "BIRDSONGS_FOLDER reverted to /config/BirdSongs"
bashio::log.warning "BIRDSONGS_FOLDER reverted to /config/BirdSongs"
fi
fi
# Create BirdSongs folder
echo "... creating default folders ; it is highly recommended to store those on a ssd"
mkdir -p "$BIRDSONGS_FOLDER"/By_Date
mkdir -p "$BIRDSONGS_FOLDER"/Charts
# Create default folders
echo "... creating default folders; it is highly recommended to store these on an SSD"
mkdir -p "$BIRDSONGS_FOLDER/By_Date" "$BIRDSONGS_FOLDER/Charts"
# If tmpfs is installed, use it
# Use tmpfs if installed
if df -T /tmp | grep -q "tmpfs"; then
echo "... tmpfs detected, using it for StreamData and Processed to reduce disk wear"
mkdir -p /tmp/StreamData
mkdir -p /tmp/Processed
if [ -d "$HOME"/BirdSongs/StreamData ]; then
rm -r "$HOME"/BirdSongs/StreamData
fi
if [ -d "$HOME"/BirdSongs/Processed ]; then
rm -r "$HOME"/BirdSongs/Processed
fi
sudo -u pi ln -fs /tmp/StreamData "$HOME"/BirdSongs/StreamData
sudo -u pi ln -fs /tmp/Processed "$HOME"/BirdSongs/Processed
mkdir -p /tmp/StreamData /tmp/Processed
[ -d "$HOME/BirdSongs/StreamData" ] && rm -r "$HOME/BirdSongs/StreamData"
[ -d "$HOME/BirdSongs/Processed" ] && rm -r "$HOME/BirdSongs/Processed"
sudo -u pi ln -fs /tmp/StreamData "$HOME/BirdSongs/StreamData"
sudo -u pi ln -fs /tmp/Processed "$HOME/BirdSongs/Processed"
fi
# Permissions for created files and folders
echo "... set permissions to user pi"
# Set permissions for created files and folders
echo "... setting permissions for user pi"
chown -R pi:pi /config /etc/birdnet "$BIRDSONGS_FOLDER" /tmp
chmod -R 755 /config /config /etc/birdnet "$BIRDSONGS_FOLDER" /tmp
chmod -R 755 /config /etc/birdnet "$BIRDSONGS_FOLDER" /tmp
# Save default birdnet.conf to perform sanity check
cp "$HOME"/BirdNET-Pi/birdnet.conf "$HOME"/BirdNET-Pi/birdnet.bak
# Backup default birdnet.conf for sanity check
cp "$HOME/BirdNET-Pi/birdnet.conf" "$HOME/BirdNET-Pi/birdnet.bak"
# Symlink files
echo "... creating symlink"
for files in "$HOME/BirdNET-Pi/birdnet.conf" "$HOME/BirdNET-Pi/scripts/whitelist_species_list.txt" "$HOME/BirdNET-Pi/blacklisted_images.txt" "$HOME/BirdNET-Pi/scripts/birds.db" "$HOME/BirdNET-Pi/BirdDB.txt" "$HOME/BirdNET-Pi/scripts/disk_check_exclude.txt" "$HOME/BirdNET-Pi/apprise.txt" "$HOME/BirdNET-Pi/exclude_species_list.txt" "$HOME/BirdNET-Pi/include_species_list.txt" "$HOME/BirdNET-Pi/IdentifiedSoFar.txt" "$HOME/BirdNET-Pi/scripts/confirmed_species_list.txt"; do
filename="${files##*/}"
if [ ! -f /config/"$filename" ]; then
if [ -f "$files" ]; then
echo "... copying $filename" && sudo -u pi mv "$files" /config/
else
touch /config/"$filename"
fi
fi
if [ -e "$files" ]; then rm "$files"; fi
sudo -u pi ln -fs /config/"$filename" "$HOME/BirdNET-Pi/$filename" || bashio::log.fatal "Symlink creation failed for $filename"
sudo -u pi ln -fs /config/"$filename" "$HOME/BirdNET-Pi/scripts/$filename" || bashio::log.fatal "Symlink creation failed for $filename"
sudo -u pi ln -fs /config/"$filename" /etc/birdnet/"$filename" || bashio::log.fatal "Symlink creation failed for $filename"
# Symlink configuration files
echo "... creating symlinks for configuration files"
CONFIG_FILES=("$HOME/BirdNET-Pi/birdnet.conf" "$HOME/BirdNET-Pi/scripts/whitelist_species_list.txt" "$HOME/BirdNET-Pi/blacklisted_images.txt" "$HOME/BirdNET-Pi/scripts/birds.db" "$HOME/BirdNET-Pi/BirdDB.txt" "$HOME/BirdNET-Pi/scripts/disk_check_exclude.txt" "$HOME/BirdNET-Pi/apprise.txt" "$HOME/BirdNET-Pi/exclude_species_list.txt" "$HOME/BirdNET-Pi/include_species_list.txt" "$HOME/BirdNET-Pi/IdentifiedSoFar.txt" "$HOME/BirdNET-Pi/scripts/confirmed_species_list.txt")
for file in "${CONFIG_FILES[@]}"; do
filename="${file##*/}"
[ ! -f "/config/$filename" ] && touch "/config/$filename"
[ -e "$file" ] && rm "$file"
sudo -u pi ln -fs "/config/$filename" "$file"
sudo -u pi ln -fs "/config/$filename" "$HOME/BirdNET-Pi/scripts/$filename"
sudo -u pi ln -fs "/config/$filename" "/etc/birdnet/$filename"
done
# Symlink folders
for folders in By_Date Charts; do
echo "... creating symlink for $BIRDSONGS_FOLDER/$folders"
rm -r "$HOME/BirdSongs/Extracted/${folders:?}"
sudo -u pi ln -fs "$BIRDSONGS_FOLDER"/"$folders" "$HOME/BirdSongs/Extracted/$folders"
# Symlink BirdSongs folders
for folder in By_Date Charts; do
echo "... creating symlink for $BIRDSONGS_FOLDER/$folder"
[ -d "$HOME/BirdSongs/Extracted/${folder:?}" ] && rm -r "$HOME/BirdSongs/Extracted/$folder"
sudo -u pi ln -fs "$BIRDSONGS_FOLDER/$folder" "$HOME/BirdSongs/Extracted/$folder"
done
# Permissions for created files and folders
echo "... check permissions"
# Set permissions for newly created files and folders
echo "... checking and setting permissions"
chmod -R 755 /config/*
chmod 777 /config
echo " "
# Create Matplotlib configuration directory
echo "... setting up Matplotlabdir"
MPLCONFIGDIR="${MPLCONFIGDIR:-$HOME/.config/matplotlib}"
mkdir -p "$MPLCONFIGDIR"
chown pi:pi "$MPLCONFIGDIR"
chmod 777 "$MPLCONFIGDIR"

View File

@@ -1,24 +1,36 @@
#!/usr/bin/with-contenv bashio
#!/command/with-contenv bashio
# shellcheck shell=bash
set -e
# Check if there are files in "$HOME"/BirdSongs/StreamData and move them to /data/StreamData
if [ -d /data/StreamData ] && [ "$(ls -A /data/StreamData/)" ]; then
if [ -d /data/StreamData ]; then
bashio::log.fatal "Container was stopped while files were still being analyzed."
bashio::log.warning "Container was stopped while files were still being analysed, restoring them"
# Check if there are .wav files in /data/StreamData
if find /data/StreamData -type f -name "*.wav" | grep -q .; then
bashio::log.warning "Restoring .wav files from /data/StreamData to $HOME/BirdSongs/StreamData."
# Copy files
if [ "$(ls -A /data/StreamData)" ]; then
mv -v /data/StreamData/* "$HOME"/BirdSongs/StreamData/
# Create the destination directory if it does not exist
mkdir -p "$HOME"/BirdSongs/StreamData
# Count the number of .wav files to be moved
file_count=$(find /data/StreamData -type f -name "*.wav" | wc -l)
echo "... found $file_count .wav files to restore."
# Move the .wav files using `mv` to avoid double log entries
mv -v /data/StreamData/*.wav "$HOME"/BirdSongs/StreamData/
# Update permissions only if files were moved successfully
if [ "$file_count" -gt 0 ]; then
chown -R pi:pi "$HOME"/BirdSongs/StreamData
fi
echo "... $file_count files restored successfully."
else
echo "... no .wav files found to restore."
fi
echo "... done"
echo ""
# Setting permissions
chown -R pi:pi "$HOME"/BirdSongs
chmod -R 755 "$HOME"/BirdSongs
# Cleaning folder
rm -r /data/StreamData
# Clean up the source folder if it is empty
if [ -z "$(ls -A /data/StreamData)" ]; then
rm -r /data/StreamData
fi
fi

View File

@@ -6,49 +6,55 @@ set -e
# CHECK BIRDNET.CONF #
######################
echo " "
bashio::log.info "Checking your birndet.conf file integrity"
bashio::log.info "Checking your birdnet.conf file integrity"
# Set variables
configcurrent="$HOME"/BirdNET-Pi/birdnet.conf
configtemplate="$HOME"/BirdNET-Pi/birdnet.bak
# Ensure both files exist before proceeding
if [ ! -f "$configcurrent" ] || [ ! -f "$configtemplate" ]; then
bashio::log.fatal "Missing required birdnet.conf or birdnet.bak file. Please ensure both are present."
exit 1
fi
# Extract variable names from config template and read each one
grep -o '^[^#=]*=' "$configtemplate" | sed 's/=//' | while read -r var; do
# Check if the variable is in configcurrent, if not, append it
if ! grep -q "^$var=" "$configcurrent"; then
# At which line was the variable in the initial file
bashio::log.yellow "...$var was missing from your birdnet.conf file, it was re-added"
bashio::log.warning "...$var was missing from your birdnet.conf file, it was re-added"
grep "^$var=" "$configtemplate" >> "$configcurrent"
fi
# Check for duplicates
if [ "$(grep -c "^$var=" "$configcurrent")" -gt 1 ]; then
bashio::log.error "Duplicate variable $var found in $configcurrent, all were commented out expect for the first one"
awk -v var="$var" '{ if ($0 ~ "^[[:blank:]]*"var && c++ > 0) print "#" $0; else print $0; }' "$configcurrent" > temp && mv temp "$configcurrent"
bashio::log.error "Duplicate variable $var found in $configcurrent, all were commented out except for the first one"
sed -i "0,/^$var=/!s/^$var=/#$var=/" "$configcurrent"
fi
done
################
# CHECK AMIXER #
################
# If default capture is set at 0%, increase it to 50%
# current_volume="$(amixer sget Capture | grep -oP '\[\d+%]' | tr -d '[]%' | head -1)" 2>/dev/null || true
# current_volume="${current_volume:-100}"
# Set the default microphone volume to 50% if it's currently at 0%
# if [[ "$current_volume" -eq 0 ]]; then
# amixer sset Capture 70%
# bashio::log.warning "Microphone was off, volume set to 70%."
# fi
##############
# CHECK PORT #
##############
if [[ "$(bashio::addon.port "80")" == 3000 ]]; then
bashio::log.fatal "This is crazy but your port is set to 3000 and streamlit doesn't accept this port! You need to change it from the addon options and restart. Thanks"
sleep infinity
bashio::log.fatal "This is crazy but your port is set to 3000 and streamlit doesn't accept this port! You need to change it from the addon options and restart. Thanks"
sleep infinity
fi
echo " "
##################
# PERFORM UPDATE #
##################
bashio::log.info "Performing potential updates"
# Adapt update_birdnet_snippets
sed -i "s|systemctl list-unit-files|false \&\& echo|g" "$HOME"/BirdNET-Pi/scripts/update_birdnet_snippets.sh
sed -i "/systemctl /d" "$HOME"/BirdNET-Pi/scripts/update_birdnet_snippets.sh
sed -i "/find /d" "$HOME"/BirdNET-Pi/scripts/update_birdnet_snippets.sh
sed -i "/set -x/d" "$HOME"/BirdNET-Pi/scripts/update_birdnet_snippets.sh
sed -i "/restart_services/d" "$HOME"/BirdNET-Pi/scripts/update_birdnet_snippets.sh
sed -i "s|/etc/birdnet/birdnet.conf|/config/birdnet.conf|g" "$HOME"/BirdNET-Pi/scripts/update_birdnet_snippets.sh
# Execute update_birdnet_snippets
"$HOME"/BirdNET-Pi/scripts/update_birdnet_snippets.sh

View File

@@ -1,70 +0,0 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -e
# Function to perform common setup steps
common_steps () {
# Attempt to connect to the MQTT broker
TOPIC="birdnet"
if mosquitto_pub -h "$MQTT_HOST" -p "$MQTT_PORT" -t "$TOPIC" -m "test" -u "$MQTT_USER" -P "$MQTT_PASS" -q 1 -d --will-topic "$TOPIC" --will-payload "Disconnected" --will-qos 1 --will-retain > /dev/null 2>&1; then
# Adapt script with MQTT settings
sed -i "s|%%mqtt_server%%|$MQTT_HOST|g" /helpers/birdnet_to_mqtt.py
sed -i "s|%%mqtt_port%%|$MQTT_PORT|g" /helpers/birdnet_to_mqtt.py
sed -i "s|%%mqtt_user%%|$MQTT_USER|g" /helpers/birdnet_to_mqtt.py
sed -i "s|%%mqtt_pass%%|$MQTT_PASS|g" /helpers/birdnet_to_mqtt.py
# Copy script to the appropriate directory
cp /helpers/birdnet_to_mqtt.py "$HOME"/BirdNET-Pi/scripts/utils/birdnet_to_mqtt.py
chown pi:pi "$HOME"/BirdNET-Pi/scripts/utils/birdnet_to_mqtt.py
chmod +x "$HOME"/BirdNET-Pi/scripts/utils/birdnet_to_mqtt.py
# Add hooks to the main analysis script
sed -i "/load_global_model, run_analysis/a from utils.birdnet_to_mqtt import automatic_mqtt_publish" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i '/write_to_db(/a\ automatic_mqtt_publish(file, detection, os.path.basename(detection.file_name_extr))' "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
else
bashio::log.fatal "MQTT connection failed, it will not be configured. Error message :"
mosquitto_pub -h "$MQTT_HOST" -p "$MQTT_PORT" -t "$TOPIC" -m "test" -u "$MQTT_USER" -P "$MQTT_PASS" -q 1 -d --will-topic "$TOPIC" --will-payload "Disconnected" --will-qos 1 --will-retain
fi
}
# Check if MQTT service is available and not disabled
if bashio::services.available 'mqtt' && ! bashio::config.true 'MQTT_DISABLED'; then
bashio::log.green "---"
bashio::log.blue "MQTT addon is active on your system! BirdNET-Pi is now automatically configured to send its output to MQTT"
bashio::log.blue "MQTT user : $(bashio::services "mqtt" "username")"
bashio::log.blue "MQTT password : $(bashio::services "mqtt" "password")"
bashio::log.blue "MQTT broker : tcp://$(bashio::services "mqtt" "host"):$(bashio::services "mqtt" "port")"
bashio::log.green "---"
bashio::log.blue "Data will be posted to the topic : 'birdnet'"
bashio::log.blue "Json data : {'Date', 'Time', 'ScientificName', 'CommonName', 'Confidence', 'SpeciesCode', 'ClipName', 'url'}"
bashio::log.blue "---"
# Apply MQTT settings
MQTT_HOST="$(bashio::services "mqtt" "host")"
MQTT_PORT="$(bashio::services "mqtt" "port")"
MQTT_USER="$(bashio::services "mqtt" "username")"
MQTT_PASS="$(bashio::services "mqtt" "password")"
# Perform common setup steps
common_steps
# Check if manual MQTT configuration is provided
elif bashio::config.has_value "MQTT_HOST_manual" && bashio::config.has_value "MQTT_PORT_manual"; then
bashio::log.green "---"
bashio::log.blue "MQTT is manually configured in the addon options"
bashio::log.blue "BirdNET-Pi is now automatically configured to send its output to MQTT"
bashio::log.green "---"
bashio::log.blue "Data will be posted to the topic : 'birdnet'"
bashio::log.blue "Json data : {'Date', 'Time', 'ScientificName', 'CommonName', 'Confidence', 'SpeciesCode', 'ClipName', 'url'}"
bashio::log.blue "---"
# Apply manual MQTT settings
MQTT_HOST="$(bashio::config "MQTT_HOST_manual")"
MQTT_PORT="$(bashio::config "MQTT_PORT_manual")"
MQTT_USER="$(bashio::config "MQTT_USER_manual")"
MQTT_PASS="$(bashio::config "MQTT_PASSWORD_manual")"
# Perform common setup steps
common_steps
fi

View File

@@ -1,63 +0,0 @@
#!/command/with-contenv bashio
# shellcheck shell=bash
set -e
################
# ADD FEATURES #
################
echo " "
bashio::log.info "Adding optional features"
# Denoiser
#if bashio::config.true "DENOISER_ANALYSIS_ENABLED"; then
# sed -i "s|ar 48000|ar 48000 -af \"arnndn=m=sample.rnnn\"|g" "$HOME"/BirdNET-Pi/scripts/birdnet_recording.sh
# sed -i "s|ar 48000|ar 48000 -af afftdn=nr=30:nt=w:om=o|g" "$HOME"/BirdNET-Pi/scripts/birdnet_recording.sh
#fi
# Enable the Processed folder
#############################
if bashio::config.true "PROCESSED_FOLDER_ENABLED" && ! grep -q "processed_size" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py; then
echo "... Enabling the Processed folder : the last 15 wav files will be stored there"
# Adapt config.php
sed -i "/GET\[\"info_site\"\]/a\ \$processed_size = \$_GET\[\"processed_size\"\];" "$HOME"/BirdNET-Pi/scripts/config.php
sed -i "/\$contents = file_get_contents/a\ \$contents = preg_replace\(\"/PROCESSED_SIZE=\.\*/\", \"PROCESSED_SIZE=\$processed_size\", \$contents\);" "$HOME"/BirdNET-Pi/scripts/config.php
sed -i "/\"success\"/i <table class=\"settingstable\"><tr><td>" "$HOME"/BirdNET-Pi/scripts/config.php
sed -i "/\"success\"/i <h2>Processed folder management </h2>" "$HOME"/BirdNET-Pi/scripts/config.php
sed -i "/\"success\"/i <label for=\"processed_size\">Amount of files to keep after analysis :</label>" "$HOME"/BirdNET-Pi/scripts/config.php
sed -i "/\"success\"/i <input name=\"processed_size\" type=\"number\" style=\"width:6em;\" max=\"90\" min=\"0\" step=\"1\" value=\"<\?php print(\$config\['PROCESSED_SIZE'\]);?>\"/>" "$HOME"/BirdNET-Pi/scripts/config.php
sed -i "/\"success\"/i </td></tr><tr><td>" "$HOME"/BirdNET-Pi/scripts/config.php
sed -i "/\"success\"/i Processed is the directory where the formerly 'Analyzed' files are moved after extractions, mostly for troubleshooting purposes.<br>" "$HOME"/BirdNET-Pi/scripts/config.php
sed -i "/\"success\"/i This value defines the maximum amount of files that are kept before replacement with new files.<br>" "$HOME"/BirdNET-Pi/scripts/config.php
sed -i "/\"success\"/i </td></tr></table>" "$HOME"/BirdNET-Pi/scripts/config.php
sed -i "/\"success\"/i\ <br>" "$HOME"/BirdNET-Pi/scripts/config.php
# Adapt birdnet_analysis.py - move_to_processed
sed -i "/log.info('handle_reporting_queue done')/a\ os.remove(files.pop(0))" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ while len(files) > processed_size:" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ files.sort(key=os.path.getmtime)" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ files = glob.glob(os.path.join(processed_dir, '*'))" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ os.rename(file_name, os.path.join(processed_dir, os.path.basename(file_name)))" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ processed_dir = os.path.join(get_settings()['RECS_DIR'], 'Processed')" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\def move_to_processed(file_name, processed_size):" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ " "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
# Adapt birdnet_analysis.py - get_processed_size
sed -i "/log.info('handle_reporting_queue done')/a\ return 0" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ except (ValueError, TypeError):" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ return processed_size if isinstance(processed_size, int) else 0" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ processed_size = get_settings().getint('PROCESSED_SIZE')" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ try:" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\def get_processed_size():" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/log.info('handle_reporting_queue done')/a\ " "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
# Modify calls
sed -i "/from subprocess import CalledProcessError/a\import glob" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/from subprocess import CalledProcessError/a\import time" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
# Modify main code
sed -i "/os.remove(file.file_name)/i\ processed_size = get_processed_size()" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/os.remove(file.file_name)/i\ if processed_size > 0:" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/os.remove(file.file_name)/i\ move_to_processed(file.file_name, processed_size)" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/os.remove(file.file_name)/i\ else:" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
sed -i "/os.remove(file.file_name)/c\ os.remove(file.file_name)" "$HOME"/BirdNET-Pi/scripts/birdnet_analysis.py
fi || true
echo " "

View File

@@ -6,61 +6,81 @@ set -e
# MODIFY WEBUI #
################
echo " "
bashio::log.info "Adapting webui"
# Remove services tab
# Remove services tab from webui
echo "... removing System Controls from webui as should be used from HA"
sed -i '/>System Controls/d' "$HOME"/BirdNET-Pi/homepage/views.php
sed -i '/>System Controls/d' "$HOME/BirdNET-Pi/homepage/views.php"
# Remove services tab
# Remove Ram drive option from webui
echo "... removing Ram drive from webui as it is handled from HA"
sed -i '/Ram drive/{n;s/center"/center" style="display: none;"/;}' "$HOME"/BirdNET-Pi/scripts/service_controls.php
sed -i '/Ram drive/d' "$HOME"/BirdNET-Pi/scripts/service_controls.php
sed -i '/Ram drive/{n;s/center"/center" style="display: none;"/;}' "$HOME/BirdNET-Pi/scripts/service_controls.php"
sed -i '/Ram drive/d' "$HOME/BirdNET-Pi/scripts/service_controls.php"
# Correct services to start as user pi
echo "... correct services to start as pi"
for file in $(find "$HOME"/BirdNET-Pi/templates/birdnet*.service -print0 | xargs -0 basename -a) livestream.service chart_viewer.service chart_viewer.service spectrogram_viewer.service; do
if [[ "$file" != "birdnet_log.service" ]]; then
sed -i "s|ExecStart=|ExecStart=/usr/bin/sudo -u pi |g" "$HOME/BirdNET-Pi/templates/$file"
echo "... updating services to start as user pi"
while IFS= read -r file; do
if [[ "$(basename "$file")" != "birdnet_log.service" ]]; then
sed -i "s|ExecStart=|ExecStart=/usr/bin/sudo -u pi |g" "$file"
fi
done
done < <(find "$HOME/BirdNET-Pi/templates/" -name "birdnet*.service" -print)
# Send services log to container logs
echo "... send services log to container logs"
for file in $(find "$HOME"/BirdNET-Pi/templates/birdnet*.service -print0 | xargs -0 basename -a) livestream.service chart_viewer.service chart_viewer.service spectrogram_viewer.service; do
sed -i "/Service/a StandardError=append:/proc/1/fd/1" "$HOME/BirdNET-Pi/templates/$file"
sed -i "/Service/a StandardOutput=append:/proc/1/fd/1" "$HOME/BirdNET-Pi/templates/$file"
done
echo "... redirecting services logs to container logs"
while IFS= read -r file; do
sed -i "/Service/a StandardError=append:/proc/1/fd/1" "$file"
sed -i "/Service/a StandardOutput=append:/proc/1/fd/1" "$file"
done < <(find "$HOME/BirdNET-Pi/templates/" -name "birdnet*.service" -print)
# Avoid preselection in include and exclude lists
echo "... avoid preselecting options in include and exclude lists"
sed -i "s|option selected|option disabled|g" "$HOME"/BirdNET-Pi/scripts/include_list.php
sed -i "s|option selected|option disabled|g" "$HOME"/BirdNET-Pi/scripts/exclude_list.php
echo "... disabling preselecting options in include and exclude lists"
sed -i "s|option selected|option disabled|g" "$HOME/BirdNET-Pi/scripts/include_list.php"
sed -i "s|option selected|option disabled|g" "$HOME/BirdNET-Pi/scripts/exclude_list.php"
# Correct log services to show /proc/1/fd/1
echo "... show container logs in /logs"
echo "... redirecting birdnet_log service output to /logs"
sed -i "/User=pi/d" "$HOME/BirdNET-Pi/templates/birdnet_log.service"
sed -i "s|birdnet_log.sh|cat /proc/1/fd/1|g" "$HOME/BirdNET-Pi/templates/birdnet_log.service"
# Make sure config is correctly formatted.
echo "... caddyfile modifications"
#Correct instructions
# Caddyfile modifications
echo "... modifying Caddyfile configurations"
caddy fmt --overwrite /etc/caddy/Caddyfile
#Change port to leave 80 free for certificate requests
sed -i "s|http://|http://:8081|g" /etc/caddy/Caddyfile
sed -i "s|http://|http://:8081|g" "$HOME"/BirdNET-Pi/scripts/update_caddyfile.sh
#Remove default file that blocks 80
if [ -f /etc/caddy/Caddyfile.original ]; then rm /etc/caddy/Caddyfile.original; fi
# Improve webui paths to facilitate ingress
echo "... correcting webui paths"
sed -i "s|/stats|/stats/|g" "$HOME"/BirdNET-Pi/homepage/views.php
sed -i "s|/log|/log/|g" "$HOME"/BirdNET-Pi/homepage/views.php
# If port 80 is enabled, make sure it is still 80
if [ -n "$(bashio::addon.port 80)" ] && [ "$(bashio::addon.port 80)" != 80 ]; then
bashio::log.fatal "The port 80 is enabled, but should still be 80 if you want the automatic ssl certificates generation to work"
sed -i "s|http://|http://:8081|g" "$HOME/BirdNET-Pi/scripts/update_caddyfile.sh"
if [ -f /etc/caddy/Caddyfile.original ]; then
rm /etc/caddy/Caddyfile.original
fi
echo " "
# Correct webui paths
echo "... correcting webui paths"
sed -i "s|/stats|/stats/|g" "$HOME/BirdNET-Pi/homepage/views.php"
sed -i "s|/log|/log/|g" "$HOME/BirdNET-Pi/homepage/views.php"
# Check if port 80 is correctly configured
if [ -n "$(bashio::addon.port 80)" ] && [ "$(bashio::addon.port 80)" != 80 ]; then
bashio::log.fatal "The port 80 is enabled, but should still be 80 if you want automatic SSL certificates generation to work."
fi
# Correct systemctl path
echo "... updating systemctl path"
mv /helpers/systemctl3.py /bin/systemctl
chmod a+x /bin/systemctl
# Correct timedatectl path
echo "updating timedatectl path"
mv /helpers/timedatectl /usr/bin/timedatectl
chown pi:pi /usr/bin/timedatectl
chmod a+x /usr/bin/timedatectl
# Correct timezone showing in config.php
sed -i -e '/<option disabled selected>/s/selected//' \
-e '/\$current_timezone = trim(shell_exec("timedatectl show --value --property=Timezone"));/d' \
-e "/\$date = new DateTime('now');/i \$current_timezone = trim(shell_exec(\"timedatectl show --value --property=Timezone\"));" \
-e "/\$date = new DateTime('now');/i date_default_timezone_set(\$current_timezone);" "$HOME/BirdNET-Pi/scripts/config.php"
# Correct language labels according to birdnet.conf
echo "... adapting labels according to birdnet.conf"
export "$(grep "^DATABASE_LANG" /config/birdnet.conf)" || bashio::log.warning "DATABASE_LANG not found in configuration. Using default labels."
bashio::log.info "Setting language to $DATABASE_LANG"
"$HOME/BirdNET-Pi/scripts/install_language_label_nm.sh" -l "$DATABASE_LANG" &>/dev/null || bashio::log.warning "Failed to update language labels"

View File

@@ -1,4 +1,4 @@
#!/usr/bin/with-contenv bashio
#!/command/with-contenv bashio
# shellcheck shell=bash
set -e
@@ -6,32 +6,55 @@ set -e
# NGINX SETTING #
#################
declare ingress_interface
declare ingress_port
declare ingress_entry
# Variables
ingress_port=$(bashio::addon.ingress_port)
ingress_interface=$(bashio::addon.ip_address)
ingress_entry=$(bashio::addon.ingress_entry)
# Quits if ingress not active
if [ -z "$ingress_entry" ]; then exit 0; fi
# Quits if ingress is not active
if [ -z "$ingress_entry" ]; then
bashio::log.warning "Ingress entry is not set, exiting configuration."
exit 0
fi
echo " "
bashio::log.info "Adapting for ingress"
echo "... setting up nginx"
sed -i "s/%%port%%/${ingress_port}/g" /etc/nginx/servers/ingress.conf
sed -i "s/%%interface%%/${ingress_interface}/g" /etc/nginx/servers/ingress.conf
sed -i "s|%%ingress_entry%%|${ingress_entry}|g" /etc/nginx/servers/ingress.conf
# Check if the NGINX configuration file exists
nginx_conf="/etc/nginx/servers/ingress.conf"
if [ -f "$nginx_conf" ]; then
sed -i "s/%%port%%/${ingress_port}/g" "$nginx_conf"
sed -i "s/%%interface%%/${ingress_interface}/g" "$nginx_conf"
sed -i "s|%%ingress_entry%%|${ingress_entry}|g" "$nginx_conf"
else
bashio::log.error "NGINX configuration file not found: $nginx_conf"
exit 1
fi
echo "... ensuring restricted area access"
echo "${ingress_entry}" > /ingress_url
sed -i "/function is_authenticated/a if (strpos(\$_SERVER['HTTP_REFERER'], '/api/hassio_ingress') !== false && strpos(\$_SERVER['HTTP_REFERER'], trim(file_get_contents('/ingress_url'))) !== false) { \$ret = true; return \$ret; }" "$HOME"/BirdNET-Pi/scripts/common.php
echo "... adapt Caddyfile for ingress"
# Modify PHP file safely
php_file="$HOME/BirdNET-Pi/scripts/common.php"
if [ -f "$php_file" ]; then
sed -i "/function is_authenticated/a if (strpos(\$_SERVER['HTTP_REFERER'], '/api/hassio_ingress') !== false && strpos(\$_SERVER['HTTP_REFERER'], trim(file_get_contents('/ingress_url'))) !== false) { \$ret = true; return \$ret; }" "$php_file"
else
bashio::log.error "PHP file not found: $php_file"
exit 1
fi
echo "... adapting Caddyfile for ingress"
chmod +x /helpers/caddy_ingress.sh
/./helpers/caddy_ingress.sh
sed -i "/sudo caddy fmt --overwrite/i /./helpers/caddy_ingress.sh" "$HOME"/BirdNET-Pi/scripts/update_caddyfile.sh
echo " "
# Correct script execution
/helpers/caddy_ingress.sh
# Update the Caddyfile if update script exists
caddy_update_script="$HOME/BirdNET-Pi/scripts/update_caddyfile.sh"
if [ -f "$caddy_update_script" ]; then
sed -i "/sudo caddy fmt --overwrite/i /helpers/caddy_ingress.sh" "$caddy_update_script"
else
bashio::log.error "Caddy update script not found: $caddy_update_script"
exit 1
fi

View File

@@ -1,4 +1,4 @@
#!/usr/bin/with-contenv bashio
#!/command/with-contenv bashio
# shellcheck shell=bash
set -e
@@ -7,14 +7,33 @@ set -e
###############
if bashio::config.true 'ssl'; then
bashio::log.info "Ssl is enabled using addon options, setting up nginx"
bashio::log.info "SSL is enabled using addon options, setting up NGINX and Caddy."
# Check required SSL configurations
bashio::config.require.ssl
certfile=$(bashio::config 'certfile')
keyfile=$(bashio::config 'keyfile')
sed -i "2a\ tls /ssl/${certfile} /ssl/${keyfile}" /etc/caddy/Caddyfile
sed -i "s|http://:8081|https://:8081|g" /etc/caddy/Caddyfile
sed -i "s|http://:8081|https://:8081|g" "$HOME"/BirdNET-Pi/scripts/update_caddyfile.sh
sed -i "/https:/a tls /ssl/${certfile} /ssl/${keyfile}" "$HOME"/BirdNET-Pi/scripts/update_caddyfile.sh
# Ensure Caddyfile exists before modifying
caddyfile="/etc/caddy/Caddyfile"
if [ -f "$caddyfile" ]; then
sed -i "2a\ tls /ssl/${certfile} /ssl/${keyfile}" "$caddyfile"
sed -i "s|http://:8081|https://:8081|g" "$caddyfile"
else
bashio::log.error "Caddyfile not found at $caddyfile, skipping SSL configuration."
exit 1
fi
# Ensure update_caddyfile.sh exists before modifying
update_script="$HOME/BirdNET-Pi/scripts/update_caddyfile.sh"
if [ -f "$update_script" ]; then
sed -i "s|http://:8081|https://:8081|g" "$update_script"
if ! grep -q "tls /ssl/${certfile} /ssl/${keyfile}" "$update_script"; then
sed -i "/https:/a\ tls /ssl/${certfile} /ssl/${keyfile}" "$update_script"
fi
else
bashio::log.error "Update script not found: $update_script, skipping SSL setup for update."
exit 1
fi
fi
echo " "

View File

@@ -6,67 +6,58 @@ set -e
# SET SYSTEM #
##############
echo " "
bashio::log.info "Setting password for the user pi"
echo "pi:$(bashio::config "pi_password")" | sudo chpasswd
echo "... done"
echo "pi:$(bashio::config "pi_password")" | chpasswd
bashio::log.info "Password set successfully for user pi."
echo " "
bashio::log.info "Starting system services"
bashio::log.info "Setting timezone :"
# Set TZ
# Use timezone defined in add-on options if available
if bashio::config.has_value 'TZ'; then
TIMEZONE=$(bashio::config 'TZ')
echo "... setting timezone to $TIMEZONE"
ln -snf /usr/share/zoneinfo/"$TIMEZONE" /etc/localtime
echo "$TIMEZONE" >/etc/timezone
fi || (bashio::log.fatal "Error : $TIMEZONE not found. Here is a list of valid timezones : https://manpages.ubuntu.com/manpages/focal/man3/DateTime::TimeZone::Catalog.3pm.html")
# Correcting systemctl
echo "... correcting systemctl"
mv /helpers/systemctl3.py /bin/systemctl
chmod a+x /bin/systemctl
# Correcting systemctl
echo "... correcting datetimectl"
mv /helpers/timedatectl /usr/bin/timedatectl
chmod a+x /usr/bin/timedatectl
# Correct language labels
export "$(grep "^DATABASE_LANG" /config/birdnet.conf)"
# Saving default of en
cp "$HOME"/BirdNET-Pi/model/labels.txt "$HOME"/BirdNET-Pi/model/labels.bak
# Adapt to new language
echo "... adapting labels according to birdnet.conf file to $DATABASE_LANG"
/."$HOME"/BirdNET-Pi/scripts/install_language_label_nm.sh -l "$DATABASE_LANG"
echo "... starting cron"
systemctl start cron
# Starting dbus
echo "... starting dbus"
service dbus start
# Starting journald
# echo "... starting journald"
# systemctl start systemd-journald
# Starting services
echo ""
bashio::log.info "Starting BirdNET-Pi services"
chmod +x "$HOME"/BirdNET-Pi/scripts/restart_services.sh
"$HOME"/BirdNET-Pi/scripts/restart_services.sh
if bashio::config.true LIVESTREAM_BOOT_ENABLED; then
echo "... starting livestream"
sudo systemctl enable icecast2
sudo systemctl start icecast2.service
sudo systemctl enable --now livestream.service
TZ_VALUE="$(bashio::config 'TZ')"
if timedatectl set-timezone "$TZ_VALUE"; then
echo "... timezone set to $TZ_VALUE as defined in add-on options (BirdNET config ignored)."
else
bashio::log.warning "Couldn't set timezone to $TZ_VALUE. Refer to the list of valid timezones: https://manpages.ubuntu.com/manpages/focal/man3/DateTime::TimeZone::Catalog.3pm.html"
timedatectl set-ntp true &>/dev/null
fi
# Use BirdNET-defined timezone if no add-on option is provided
elif [ -f /data/timezone ]; then
BIRDN_CONFIG_TZ="$(cat /data/timezone)"
timedatectl set-ntp false &>/dev/null
if timedatectl set-timezone "$BIRDN_CONFIG_TZ"; then
echo "... set to $BIRDN_CONFIG_TZ as defined in BirdNET config."
else
bashio::log.warning "Couldn't set timezone to $BIRDN_CONFIG_TZ. Reverting to automatic timezone."
timedatectl set-ntp true &>/dev/null
fi
# Fallback to automatic timezone if no manual settings are found
else
if timedatectl set-ntp true &>/dev/null; then
bashio::log.info "... automatic timezone enabled."
else
bashio::log.fatal "Couldn't set automatic timezone! Please set a manual one from the options."
fi
fi
# Correct the phpsysinfo for the correct gotty service
gottyservice="$(pgrep -l "gotty" | awk '{print $NF}' | head -n 1)"
echo "... using $gottyservice in phpsysinfo"
sed -i "s/,gotty,/,${gottyservice:-gotty},/g" "$HOME"/BirdNET-Pi/templates/phpsysinfo.ini
bashio::log.info "Starting system services"
echo " "
bashio::log.info "Starting cron service"
systemctl start cron >/dev/null
bashio::log.info "Starting dbus service"
service dbus start >/dev/null
bashio::log.info "Starting BirdNET-Pi services"
chmod +x "$HOME/BirdNET-Pi/scripts/restart_services.sh" >/dev/null
"$HOME/BirdNET-Pi/scripts/restart_services.sh" >/dev/null
# Start livestream services if enabled in configuration
if bashio::config.true LIVESTREAM_BOOT_ENABLED; then
echo "... starting livestream services"
systemctl enable icecast2 >/dev/null
systemctl start icecast2.service >/dev/null
systemctl enable --now livestream.service >/dev/null
fi
bashio::log.info "Setup complete."