16 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
0b4da732ca Fix Settings.yaml corruption: move bashio::log calls outside stdout redirect block
The bashio-standalone.sh library writes log output to stdout (fd 1), not to
a preserved LOG_FD like the real bashio library. When bashio::log.info calls
were inside the { ... } > Settings.yaml block in immich_frame's 99-run.sh,
log messages leaked into the generated YAML file, corrupting it and causing
ImmichFrame to fail to parse account configuration correctly.

Changes:
- bashio-standalone.sh: redirect log output to LOG_FD (if available) or
  stderr, matching real bashio behavior
- bashio-standalone.sh: add missing bashio::log.fatal and bashio::log.notice
  aliases
- immich_frame 99-run.sh: move all bashio::log calls outside the
  { ... } > Settings.yaml block so only YAML content goes to the file

Agent-Logs-Url: https://github.com/alexbelgium/hassio-addons/sessions/87f542ba-1e4a-4b71-a787-e979818997df

Co-authored-by: alexbelgium <44178713+alexbelgium@users.noreply.github.com>
2026-04-17 12:06:52 +00:00
copilot-swe-agent[bot]
82b0182b6a Initial plan 2026-04-17 11:53:13 +00:00
Alexandre
bb0aae2a32 Merge pull request #2652 from Suncuss/fix/birdnet-pipy-self-update-core-api
birdnet-pipy: enable Core API for in-app self-update
2026-04-17 08:38:47 +02:00
Yudong Sun
2fb26d4aa9 birdnet-pipy: enable Core API for in-app self-update
Adds `homeassistant_api: true` so the addon can call HA Core's
`update.install` service. Required for in-app self-update —
Supervisor blocks `/store/addons/<self>/update`, so the backend
routes through Core.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-17 01:53:51 -04:00
Alexandre
961444aad7 Merge pull request #2651 from Suncuss/fix/birdnet-pipy-remove-tz-option
birdnet-pipy: remove TZ option — timezone auto-derived from station location
2026-04-15 16:02:23 +02:00
Yudong Sun
33000347b4 birdnet-pipy: remove TZ option — timezone auto-derived from station location
The app derives its timezone from station lat/lng via timezonefinder
(Settings → Location in the Web UI), so a separate addon-level TZ only
ever created mismatch with the UI-derived zone. All app-facing timestamps
(dashboard, API, DB) and Python service stdout (api/main/birdnet) already
honor the UI zone via logging_config.py's formatter, and the frontend log
viewer re-converts Icecast timestamps on read.

Net effect in the HA addon log pane: Python services still show the
correct local time; only Icecast's raw stdout now prints in UTC (accepted
trade for a single source of truth). Deletes
rootfs/etc/cont-init.d/02-timezone.sh added in 0.5.6-2.

Also cleans up the options YAML in DOCS.md/README.md: drops
RECORDING_MODE and RTSP_URL (never wired — app reads them from
user_settings.json), drops http_stream from the modes list, and moves
STREAM_BITRATE under an env_vars: example since it's honored by
start-icecast.sh but not a schema option.

Bumped to 0.6.3-2 (addon-only, no upstream app change).
2026-04-15 08:54:17 -04:00
github-actions
17df410999 GitHub bot: changelog [nobuild] 2026-04-14 13:27:29 +00:00
Alexandre
02326d8533 Merge pull request #2650 from alexbelgium/copilot/fix-storage-folder-recognition
Fix Linkwarden STORAGE_FOLDER path resolution for persistent storage
2026-04-14 15:24:17 +02:00
copilot-swe-agent[bot]
2b93184d25 Improve warning message clarity for data migration failures
Agent-Logs-Url: https://github.com/alexbelgium/hassio-addons/sessions/58467521-7d29-4fad-99f8-aad56f0540b8

Co-authored-by: alexbelgium <44178713+alexbelgium@users.noreply.github.com>
2026-04-14 08:58:01 +00:00
copilot-swe-agent[bot]
f4f9b15628 Generalize STORAGE_FOLDER symlink fix into reusable function with comprehensive documentation
Extract fix_linkwarden_path() function that can handle any absolute path
affected by the upstream path.join(process.cwd(), '../..', ...) pattern.
Document all 6 affected upstream filesystem operations.

Agent-Logs-Url: https://github.com/alexbelgium/hassio-addons/sessions/58467521-7d29-4fad-99f8-aad56f0540b8

Co-authored-by: alexbelgium <44178713+alexbelgium@users.noreply.github.com>
2026-04-14 08:57:02 +00:00
github-actions
a2843bd5d8 GitHub bot: changelog [nobuild] 2026-04-14 08:54:41 +00:00
Alexandre
de83bf2483 Update version in config.yaml to 2.14.0-2 2026-04-14 10:52:55 +02:00
Alexandre
c422dcd695 Update version to 3.1.0-4 in config.yaml 2026-04-14 10:51:14 +02:00
copilot-swe-agent[bot]
10cb1d2629 Address review: improve error logging for data migration and add clarifying comment
Agent-Logs-Url: https://github.com/alexbelgium/hassio-addons/sessions/23af3f23-96f8-49a3-849a-82fb5feef2bc

Co-authored-by: alexbelgium <44178713+alexbelgium@users.noreply.github.com>
2026-04-14 06:33:36 +00:00
copilot-swe-agent[bot]
6768d8f019 Fix STORAGE_FOLDER not being recognized by creating symlink from resolved path to persistent location
Linkwarden resolves STORAGE_FOLDER via path.join(process.cwd(), '../..', STORAGE_FOLDER)
which produces /data_linkwarden/config/library instead of /config/library when the app
runs from apps/web or apps/worker subdirectories. The symlink ensures data written to the
resolved path ends up in the persistent addon config directory.

Agent-Logs-Url: https://github.com/alexbelgium/hassio-addons/sessions/23af3f23-96f8-49a3-849a-82fb5feef2bc

Co-authored-by: alexbelgium <44178713+alexbelgium@users.noreply.github.com>
2026-04-14 06:32:37 +00:00
copilot-swe-agent[bot]
f80a8a9072 Initial plan 2026-04-14 06:23:26 +00:00
12 changed files with 103 additions and 60 deletions

View File

@@ -47,7 +47,14 @@ _bashio_color() {
_bashio_log() {
local c="${1:-}"; shift || true
printf '%s%s%s\n' "$(_bashio_color "$c")" "$*" "$(_bashio_color reset)"
# Use LOG_FD (set by real bashio) if available, otherwise stderr.
# This prevents log output from leaking into stdout when it is redirected
# (e.g., { echo yaml; } > file).
if [[ "${LOG_FD:-}" =~ ^[0-9]+$ ]] && { : >&"${LOG_FD}"; } 2>/dev/null; then
printf '%s%s%s\n' "$(_bashio_color "$c")" "$*" "$(_bashio_color reset)" >&"$LOG_FD"
else
printf '%s%s%s\n' "$(_bashio_color "$c")" "$*" "$(_bashio_color reset)" >&2
fi
}
# -----------------------------------------------------------------------------
@@ -155,9 +162,11 @@ bashio::log.magenta() { _bashio_log magenta "$*"; }
# Common aliases
bashio::log.info() { bashio::log.blue "$@"; }
bashio::log.notice() { bashio::log.blue "$@"; }
bashio::log.warning() { bashio::log.yellow "$@"; }
bashio::log.error() { bashio::log.red "$@"; }
bashio::log.debug() { printf '%s\n' "$*"; }
bashio::log.fatal() { bashio::log.red "$@"; }
bashio::log.debug() { _bashio_log "" "$*"; }
# -----------------------------------------------------------------------------
# Supervisor shim

View File

@@ -1,3 +1,10 @@
## 0.6.3-3 (2026-04-17)
- Enable Core API access (`homeassistant_api: true`) so the addon can call HA Core's `update.install` service. Required for in-app self-update — Supervisor blocks `/store/addons/<self>/update`, so the backend routes through Core.
## 0.6.3-2 (2026-04-15)
- Remove the `TZ` add-on option. Application timezone is now auto-derived in the Web UI from the station location (latitude/longitude) via `timezonefinder`, so a separately-configured container `TZ` only ever duplicated — and occasionally conflicted with — the UI-derived zone. All app-facing timestamps (dashboard, API responses, database) and Python service stdout (`api`/`main`/`birdnet`) already honor the UI-derived zone via the logging formatter; the frontend log viewer also re-converts Icecast timestamps on read. Net effect in the HA addon log pane: Python logs keep their local-time timestamps; only Icecast's raw stdout now prints in UTC — an intentional trade for a single source of truth. Deletes the now-redundant `rootfs/etc/cont-init.d/02-timezone.sh` added in 0.5.6-2.
- Clean up the options YAML in DOCS.md and README.md. Removed `RECORDING_MODE` and `RTSP_URL` — these were documented as addon options but never wired: the app reads them from `user_settings.json` (configured via the Web UI), not from env vars. Also dropped `http_stream` from the list of modes (only `pulseaudio` and `rtsp` remain in `backend/config/constants.py`). Moved `STREAM_BITRATE` under an `env_vars:` example since it's honored by `start-icecast.sh` but has never been a first-class option in the schema.
## 0.6.3 (2026-04-13)
- Simplify ingress nginx to a single `<base href>` rewrite. Upstream now declares `<base href="/">` in `index.html` with Vite `base: './'` and uses relative paths for all internal URLs (built assets, axios `baseURL`, socket.io `path`). The previous seven `sub_filter` rules (href/src/`/api`/`/socket.io`) are no longer needed — one `<base href>` replacement is sufficient.
- Removes incidental brittleness from byte-level `sub_filter` matches in minified JS bundles (the old `/stream/` rule had inadvertently double-prefixed the literal `api.get("/stream/config")` string).

View File

@@ -15,14 +15,13 @@
## Options
```yaml
TZ: Europe/Paris # Timezone, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
ICECAST_PASSWORD: "" # Optional: set a persistent password for the audio stream
STREAM_BITRATE: 320k # Bitrate for the mp3 stream
RECORDING_MODE: rtsp # pulseaudio | http_stream | rtsp
RTSP_URL: "" # Required if RECORDING_MODE is rtsp
data_location: /config/data # Persistent data location for BirdNET-PiPy
ICECAST_PASSWORD: "" # Optional: persistent password for the Icecast audio stream
data_location: /config/data # Persistent data location (under /config, /share, or /data)
env_vars: # Optional: extra environment variables
- name: STREAM_BITRATE
value: 320k # Icecast mp3 stream bitrate (default 320k)
```
## Audio
The add-on expects audio via PulseAudio (default) or an RTSP stream configured in the BirdNET-PiPy settings.
The add-on expects audio via PulseAudio (default) or an RTSP stream. Pick the source in the BirdNET-PiPy Web UI under **Settings → Audio** after the add-on first starts.

View File

@@ -25,12 +25,11 @@ Options can be configured through three ways:
- Add-on options
```yaml
TZ: Etc/UTC # Timezone, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
ICECAST_PASSWORD: "" # Optional: set a persistent password for the audio stream
STREAM_BITRATE: 320k # Bitrate for the mp3 stream
RECORDING_MODE: rtsp # pulseaudio | http_stream | rtsp
RTSP_URL: "" # Required if RECORDING_MODE is rtsp
data_location: /config/data # Persistent data location for BirdNET-PiPy
ICECAST_PASSWORD: "" # Optional: persistent password for the Icecast audio stream
data_location: /config/data # Persistent data location (under /config, /share, or /data)
env_vars: # Optional: extra environment variables
- name: STREAM_BITRATE
value: 320k # Icecast mp3 stream bitrate (default 320k)
```
- Config.yaml

View File

@@ -61,6 +61,7 @@ environment:
PUID: "0"
hassio_api: true
hassio_role: manager
homeassistant_api: true
image: ghcr.io/alexbelgium/birdnet-pipy-{arch}
ingress: true
ingress_stream: true
@@ -73,7 +74,6 @@ name: BirdNET-PiPy
options:
env_vars: []
ICECAST_PASSWORD: ''
TZ: Europe/Paris
data_location: /config/data
panel_icon: mdi:bird
ports:
@@ -85,7 +85,6 @@ schema:
- name: match(^[A-Za-z0-9_]+$)
value: str?
ICECAST_PASSWORD: str?
TZ: str?
certfile: str?
cifsdomain: str?
cifspassword: str?
@@ -97,4 +96,4 @@ schema:
ssl: bool?
slug: birdnet-pipy
url: https://github.com/alexbelgium/hassio-addons/tree/master/birdnet-pipy
version: "0.6.3"
version: "0.6.3-3"

View File

@@ -1,27 +0,0 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -euo pipefail
# Use timezone defined in add-on options
bashio::log.info "Setting timezone..."
TZ_VALUE="$(bashio::config 'TZ' || true)"
TZ_VALUE="${TZ_VALUE:-Europe/Paris}"
if [ ! -f "/usr/share/zoneinfo/${TZ_VALUE}" ]; then
bashio::log.warning "Invalid timezone '${TZ_VALUE}'. Falling back to Europe/Paris."
bashio::log.warning "See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for valid values."
TZ_VALUE="Europe/Paris"
fi
# Apply timezone to the container
ln -sf "/usr/share/zoneinfo/${TZ_VALUE}" /etc/localtime
echo "${TZ_VALUE}" > /etc/timezone
export TZ="${TZ_VALUE}"
sed -i "1a TZ=\"${TZ_VALUE}\"" /etc/services.d/*
# Update s6 container environment so child processes inherit the timezone
if [ -d /var/run/s6/container_environment ]; then
echo "${TZ_VALUE}" > /var/run/s6/container_environment/TZ
fi
bashio::log.notice "Timezone set to: ${TZ_VALUE}"

View File

@@ -115,6 +115,25 @@ ACCOUNT_SCHEMA_OPTS="Albums ExcludedAlbums People Tags ShowFavorites ShowMemorie
ShowArchived ShowVideos ImagesFromDays ImagesFromDate ImagesUntilDate Rating"
# ---- Build Settings.yaml ----
# Determine account configuration mode (and validate) before writing the file
ACCOUNT_COUNT=$(jq '.Accounts // [] | length' /data/options.json 2>/dev/null || echo 0)
if [ "$ACCOUNT_COUNT" -gt 0 ]; then
ACCOUNT_MODE="accounts_list"
bashio::log.info "Configuring ${ACCOUNT_COUNT} account(s) from Accounts list"
elif config_has '.ApiKey' && config_has '.ImmichServerUrl'; then
ACCOUNT_MODE="single"
bashio::log.info "Using single account configuration"
elif [ -n "${ACCOUNT_ENVS[ImmichServerUrl]:-}" ] && [ -n "${ACCOUNT_ENVS[ApiKey]:-}" ]; then
ACCOUNT_MODE="env_vars"
bashio::log.info "Using account configuration from env_vars"
else
bashio::log.fatal "No accounts configured! Set either 'Accounts' list or both 'ApiKey' and 'ImmichServerUrl'"
exit 1
fi
# Generate Settings.yaml — only echo/yaml_kv inside this block (no bashio::log)
{
# -- General section --
GENERAL_STARTED=false
@@ -135,10 +154,7 @@ ACCOUNT_SCHEMA_OPTS="Albums ExcludedAlbums People Tags ShowFavorites ShowMemorie
done
# -- Accounts section --
ACCOUNT_COUNT=$(jq '.Accounts // [] | length' /data/options.json 2>/dev/null || echo 0)
if [ "$ACCOUNT_COUNT" -gt 0 ]; then
bashio::log.info "Configuring ${ACCOUNT_COUNT} account(s) from Accounts list"
if [ "$ACCOUNT_MODE" = "accounts_list" ]; then
echo "Accounts:"
for i in $(seq 0 $((ACCOUNT_COUNT - 1))); do
SRV="$(config_val ".Accounts[${i}].ImmichServerUrl")"
@@ -159,12 +175,9 @@ ACCOUNT_SCHEMA_OPTS="Albums ExcludedAlbums People Tags ShowFavorites ShowMemorie
yaml_kv " " "$key" "${ACCOUNT_ENVS[$key]}"
fi
done
bashio::log.info " Account $((i + 1)): ${SRV}"
done
elif config_has '.ApiKey' && config_has '.ImmichServerUrl'; then
bashio::log.info "Using single account configuration"
elif [ "$ACCOUNT_MODE" = "single" ]; then
SRV="$(config_val '.ImmichServerUrl')"
KEY="$(config_val '.ApiKey')"
echo "Accounts:"
@@ -177,8 +190,7 @@ ACCOUNT_SCHEMA_OPTS="Albums ExcludedAlbums People Tags ShowFavorites ShowMemorie
yaml_kv " " "$key" "${ACCOUNT_ENVS[$key]}"
done
elif [ -n "${ACCOUNT_ENVS[ImmichServerUrl]:-}" ] && [ -n "${ACCOUNT_ENVS[ApiKey]:-}" ]; then
bashio::log.info "Using account configuration from env_vars"
elif [ "$ACCOUNT_MODE" = "env_vars" ]; then
echo "Accounts:"
echo " - ImmichServerUrl: '${ACCOUNT_ENVS[ImmichServerUrl]//\'/\'\'}'"
echo " ApiKey: '${ACCOUNT_ENVS[ApiKey]//\'/\'\'}'"
@@ -187,12 +199,16 @@ ACCOUNT_SCHEMA_OPTS="Albums ExcludedAlbums People Tags ShowFavorites ShowMemorie
in_list "$key" " ImmichServerUrl ApiKey " && continue
yaml_kv " " "$key" "${ACCOUNT_ENVS[$key]}"
done
else
bashio::log.fatal "No accounts configured! Set either 'Accounts' list or both 'ApiKey' and 'ImmichServerUrl'"
exit 1
fi
} > "${SETTINGS_FILE}"
# Log account details after YAML generation
if [ "$ACCOUNT_MODE" = "accounts_list" ]; then
for i in $(seq 0 $((ACCOUNT_COUNT - 1))); do
bashio::log.info " Account $((i + 1)): $(config_val ".Accounts[${i}].ImmichServerUrl")"
done
fi
chmod 600 "${SETTINGS_FILE}"
bashio::log.info "Settings.yaml generated at ${SETTINGS_FILE}"

View File

@@ -1,3 +1,5 @@
## 2.14.0-2 (14-04-2026)
- Minor bugs fixed
## 2.14.0 (2026-03-28)
- Update to latest version from linkwarden/linkwarden (changelog : https://github.com/linkwarden/linkwarden/releases)

View File

@@ -45,5 +45,5 @@ schema:
STORAGE_FOLDER: str?
slug: linkwarden
url: https://github.com/alexbelgium/hassio-addons/tree/master/linkwarden
version: "2.14.0"
version: "2.14.0-2"
webui: "[PROTO:ssl]://[HOST]:[PORT:3000]"

View File

@@ -9,6 +9,43 @@ set -e
bashio::log.info "Creating folders"
mkdir -p "$STORAGE_FOLDER"
# Upstream Linkwarden (packages/filesystem/*.ts) resolves STORAGE_FOLDER via:
# path.join(process.cwd(), '../..', STORAGE_FOLDER, filePath)
# The yarn workspace commands run from apps/web/ or apps/worker/, so
# process.cwd()/../.. resolves to the monorepo root /data_linkwarden.
# Node.js path.join treats absolute path segments as relative when they are not
# the first argument, so an absolute STORAGE_FOLDER like /config/library becomes
# /data_linkwarden/config/library instead of /config/library.
# This affects all filesystem operations: createFile, createFolder, readFile,
# moveFile, removeFile, removeFolder.
# Fix: symlink the top-level directory so all subpaths resolve correctly.
fix_linkwarden_path() {
local actual_path="$1"
local resolved_path="/data_linkwarden${actual_path}"
# Only needed for absolute paths that differ after prefixing
if [ "$resolved_path" = "$actual_path" ]; then
return
fi
mkdir -p "$(dirname "$resolved_path")"
# Preserve any data already written to the non-persistent path
if [ -d "$resolved_path" ] && [ ! -L "$resolved_path" ]; then
if ! cp -rn "$resolved_path/." "$actual_path/" 2>/dev/null; then
bashio::log.warning "Could not migrate existing data from $resolved_path to $actual_path (may be empty or a permissions issue)"
fi
rm -rf "$resolved_path"
fi
ln -sfn "$actual_path" "$resolved_path"
bashio::log.info "Symlinked $resolved_path -> $actual_path"
}
if [[ "$STORAGE_FOLDER" == /* ]]; then
fix_linkwarden_path "$STORAGE_FOLDER"
fi
######################
# CONFIGURE POSTGRES #
######################

View File

@@ -1,3 +1,5 @@
## 3.1.0-4 (14-04-2026)
- Minor bugs fixed
## 3.1.0-3 (14-04-2026)
- Minor bugs fixed

View File

@@ -95,4 +95,4 @@ schema:
slug: seerr
udev: true
url: https://github.com/alexbelgium/hassio-addons/tree/master/seerr
version: "3.1.0-3"
version: "3.1.0-4"