From 97c22977d002739a6d5f2f26f014836d7dc58dd3 Mon Sep 17 00:00:00 2001 From: Samuel ORTION Date: Wed, 24 Aug 2022 14:12:42 +0200 Subject: [PATCH] db: Add mysql support for birdnet_observation database --- .../database/scripts => .ideas}/database.py | 0 config/birdnet.conf.example | 4 +- daemon/database/scripts/create.sh | 15 ++++- daemon/database/scripts/database.sh | 26 ++++++++- daemon/database/structure-mysql.sql | 31 ++++++++++ .../{structure.sql => structure-sqlite.sql} | 8 +-- docs/DATABASE.md | 58 +++++++++++++++++++ 7 files changed, 130 insertions(+), 12 deletions(-) rename {daemon/database/scripts => .ideas}/database.py (100%) create mode 100644 daemon/database/structure-mysql.sql rename daemon/database/{structure.sql => structure-sqlite.sql} (77%) create mode 100644 docs/DATABASE.md diff --git a/daemon/database/scripts/database.py b/.ideas/database.py similarity index 100% rename from daemon/database/scripts/database.py rename to .ideas/database.py diff --git a/config/birdnet.conf.example b/config/birdnet.conf.example index b26d102..6a95699 100644 --- a/config/birdnet.conf.example +++ b/config/birdnet.conf.example @@ -19,6 +19,4 @@ PYTHON_VENV="./.venv/birdnet-stream" WORKDIR="/home/$USER/BirdNET-stream" # Database location DATABASE="./var/db.sqlite" - -DAEMON_USER="birdnet" -DAEMON_PASSWORD="secret" \ No newline at end of file +# DATABASE="mysql://birdnet:secret@localhost:3306/birdnet_observations" # uncomment and change 'secret' if you want to use a mariadb (mysql) database instea of sqlite diff --git a/daemon/database/scripts/create.sh b/daemon/database/scripts/create.sh index bb9359f..1cafead 100755 --- a/daemon/database/scripts/create.sh +++ b/daemon/database/scripts/create.sh @@ -17,5 +17,16 @@ if [ -z "$DATABASE" ]; then DATABASE="./var/db.sqlite" fi -# Create database according to schema in structure.sql -sqlite3 "$DATABASE" < ./daemon/database/structure.sql \ No newline at end of file +if [[ $DATABASE = "mysql://"* ]]; then + # Split mysql uri into user, password, host, port, and database + MYSQL_ADDRESS=$(echo "$DATABASE" | sed 's/mysql:\/\///g') + MYSQL_CREDENTIALS=$(echo "$MYSQL_ADDRESS" | cut -d@ -f1) + MYSQL_USER=$(echo "$MYSQL_CREDENTIALS" | cut -d: -f1) + MYSQL_PASSWORD=$(echo "$MYSQL_CREDENTIALS" | cut -d: -f2) + MYSQL_HOST=$(echo "$MYSQL_ADDRESS" | cut -d@ -f2 | cut -d: -f1) + MYSQL_PORT=$(echo "$MYSQL_ADDRESS" | cut -d@ -f2 | cut -d: -f2 | cut -d/ -f1) + MYSQL_DATABASE=$(echo "$MYSQL_ADDRESS" | cut -d/ -f2) + mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -h$MYSQL_HOST -P$MYSQL_PORT -D$MYSQL_DATABASE < ./daemon/database/structure-mysql.sql +else + sqlite3 $DATABASE < ./daemon/database/structure-sqlite.sql +fi diff --git a/daemon/database/scripts/database.sh b/daemon/database/scripts/database.sh index 66c8b08..049973f 100755 --- a/daemon/database/scripts/database.sh +++ b/daemon/database/scripts/database.sh @@ -8,10 +8,30 @@ source ./config/birdnet.conf # Create database in case it was not created yet ./daemon/database/scripts/create.sh -DATABASE=${DATABASE:-"./var/db.sqlite"} +# Check if database location is specified +if [ -z "$DATABASE" ]; then + echo "DATABASE location not specified" + echo "Defaults to ./var/db.sqlite" + DATABASE="./var/db.sqlite" +fi query() { - sqlite3 -cmd ".timeout 1000" $DATABASE "$1" + local stmt + stmt="$1" + if [[ $DATABASE = "mysql://"* ]]; then + # Split mysql uri into user, password, host, port, and database + MYSQL_ADDRESS=$(echo "$DATABASE" | sed 's/mysql:\/\///g') + MYSQL_CREDENTIALS=$(echo "$MYSQL_ADDRESS" | cut -d@ -f1) + MYSQL_USER=$(echo "$MYSQL_CREDENTIALS" | cut -d: -f1) + MYSQL_PASSWORD=$(echo "$MYSQL_CREDENTIALS" | cut -d: -f2) + MYSQL_HOST=$(echo "$MYSQL_ADDRESS" | cut -d@ -f2 | cut -d: -f1) + MYSQL_PORT=$(echo "$MYSQL_ADDRESS" | cut -d@ -f2 | cut -d: -f2 | cut -d/ -f1) + MYSQL_DATABASE=$(echo "$MYSQL_ADDRESS" | cut -d/ -f2) + mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -h$MYSQL_HOST -P$MYSQL_PORT -D$MYSQL_DATABASE -e "$stmt" + else + sqlite3 -cmd ".timeout 1000" "$DATABASE" "$stmt" + fi + } get_location_id() { @@ -37,4 +57,4 @@ insert_observation() { # Check if the observation already exists in the database observation_exists() { query "SELECT EXISTS(SELECT observation_id FROM observation WHERE audio_file='$1' AND start='$2' AND end='$3' AND taxon_id='$4' AND location_id='$5')" -} \ No newline at end of file +} diff --git a/daemon/database/structure-mysql.sql b/daemon/database/structure-mysql.sql new file mode 100644 index 0000000..e34153e --- /dev/null +++ b/daemon/database/structure-mysql.sql @@ -0,0 +1,31 @@ +/** Database structure for BirdNET-stream SQLite*/ + +/** Taxon table */ +CREATE TABLE IF NOT EXISTS taxon ( + taxon_id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, + scientific_name TEXT NOT NULL, + common_name TEXT NOT NULL +); + +/** Location table */ +CREATE TABLE IF NOT EXISTS location ( + location_id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, + latitude REAL NOT NULL, + longitude REAL NOT NULL +); + +/** Observation table */ +CREATE TABLE IF NOT EXISTS observation ( + `observation_id` INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, + `audio_file` TEXT NOT NULL, + `start` REAL NOT NULL, + `end` REAL NOT NULL, + `taxon_id` INTEGER NOT NULL, + `location_id` INTEGER NOT NULL, + `date` TEXT NOT NULL, + `notes` TEXT, + `confidence` REAL NOT NULL, + `verified` BOOLEAN DEFAULT 0 CHECK (`verified` IN (0, 1)), + FOREIGN KEY(taxon_id) REFERENCES taxon(taxon_id), + FOREIGN KEY(location_id) REFERENCES location(location_id) +); diff --git a/daemon/database/structure.sql b/daemon/database/structure-sqlite.sql similarity index 77% rename from daemon/database/structure.sql rename to daemon/database/structure-sqlite.sql index 23a288f..ea0c401 100644 --- a/daemon/database/structure.sql +++ b/daemon/database/structure-sqlite.sql @@ -2,21 +2,21 @@ /** Taxon table */ CREATE TABLE IF NOT EXISTS taxon ( - taxon_id INTEGER PRIMARY KEY, + taxon_id INTEGER PRIMARY KEY NOT NULL, scientific_name TEXT NOT NULL, common_name TEXT NOT NULL ); /** Location table */ CREATE TABLE IF NOT EXISTS location ( - location_id INTEGER PRIMARY KEY, + location_id INTEGER PRIMARY KEY NOT NULL, latitude REAL NOT NULL, longitude REAL NOT NULL ); /** Observation table */ CREATE TABLE IF NOT EXISTS observation ( - `observation_id` INTEGER PRIMARY KEY, + `observation_id` INTEGER PRIMARY KEY NOT NULL, `audio_file` TEXT NOT NULL, `start` REAL NOT NULL, `end` REAL NOT NULL, @@ -25,7 +25,7 @@ CREATE TABLE IF NOT EXISTS observation ( `date` TEXT NOT NULL, `notes` TEXT, `confidence` REAL NOT NULL, - `verified` BOOLEAN NOT NULL CHECK (`verified` IN (0, 1)) DEFAULT 0, + `verified` BOOLEAN DEFAULT 0 CHECK (`verified` IN (0, 1)), FOREIGN KEY(taxon_id) REFERENCES taxon(taxon_id), FOREIGN KEY(location_id) REFERENCES location(location_id) ); diff --git a/docs/DATABASE.md b/docs/DATABASE.md new file mode 100644 index 0000000..810910b --- /dev/null +++ b/docs/DATABASE.md @@ -0,0 +1,58 @@ +# Setting up the database + +There is two database managment systems available: sqlite or mariadb (mysql). + +## sqlite + +To use sqlite, simply install the sqlite3 package, if it is not already installed on the machine that runs BirdNET-stream. + +```bash +sudo apt-get install sqlite3 +``` + +Then fill `config/birdnet.conf` with the proper DATABASE value (you may use any database location): + +```bash +DATABASE="./var/db.sqlite" +``` + +## mariadb + +To use mariadb, you need to install the mariadb-server package. + +```bash +sudo apt-get install mariadb-server +``` + +Then, populate the `config/birdnet.conf` file with the proper DATABASE uri: + +```bash +DATABASE="mysql://user:password@localhost/birdnet_observations" +``` + +## Symfony configuration + +For both method you need to adapt the file `www/.env.local` to suit your new configuration. + +```bash +cd www +# If .env.local does not exists: +cp .env.local.example .env.local +``` + +```text +# .env.local +# for sqlite (example) +DATABASE_DEFAULT_URL=sqlite:///%kernel.project_dir%/./var/db-default.sqlite +DATABASE_OBSERVATIONS_URL=sqlite:///%kernel.project_dir%/../var/db.sqlite +# for mariadb (example) +DATABASE_DEFAULT_URL=mysql://user:password@localhost/birdnet_default +DATABASE_OBSERVATIONS_URL=mysql://user:password@localhost/birdnet_observations +``` + +## PHP modules + +For symfony to work, make sure you have the required modules according to each method: + +- pdo_sqlite +- pdo_mysql \ No newline at end of file