Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabling automatic update of location with GPS (via gpsd service) #42

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
730e053
First commit for location autoupdate (via gpsd) - !experimental!
Kytutr Apr 24, 2024
13061fb
Merge pull request #1 from Kytutr/experimental_gpsd_integration
Kytutr Apr 24, 2024
7ae2231
Adjusting installation scripts to my fork
Apr 25, 2024
60d21a0
Merge pull request #2 from Kytutr/adjusting_installation
Kytutr Apr 25, 2024
60724e0
Fixing BASE_URL for TL_WHL installation
Apr 25, 2024
ab4a5b3
Adjusting/fixig installation and update
Apr 25, 2024
d049839
Adding info to the README
Kytutr Apr 25, 2024
27a1148
Adding ommited [
Kytutr Apr 25, 2024
3d85ca8
Merge pull request #3 from Kytutr/adjustments_for_installation
Kytutr Apr 25, 2024
238fd74
Merge branch 'main' into location_autoupdate
Kytutr Apr 25, 2024
061ba7a
Merge pull request #4 from Kytutr/location_autoupdate
Kytutr Apr 25, 2024
46c74b4
Keeping links as they are
Kytutr Apr 25, 2024
f2e36a8
Well, let's not change too much
Kytutr Apr 25, 2024
2e9f0bf
Keeping links as they are
Kytutr Apr 25, 2024
21867a3
Keeping links as they are
Kytutr Apr 25, 2024
e267fec
Fixing updating location_autoupdate service
Kytutr Apr 25, 2024
414b3d4
Fixing updating location_autoupdate service
Kytutr Apr 25, 2024
b3c19b1
Fixing updating location_autoupdate service
Kytutr Apr 25, 2024
0d3e92a
Fixing updating location_autoupdate service - last commit for this, I…
Kytutr Apr 25, 2024
694a084
Just getting all needed fixes for update scripts
Kytutr Apr 25, 2024
04f6f5f
And one more small fix for update_birdnet_snippes.sh
Kytutr Apr 25, 2024
3af07ed
Fixing updating location_autoupdate service - one more last commit
Kytutr Apr 25, 2024
90237f4
Fixing updating location_autoupdate service - one more last commit
Kytutr Apr 25, 2024
0e6d0bd
Fixing updating location_autoupdate service - taking care about Pytho…
Kytutr Apr 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Changes include:
- Fix: changing advanced settings was not updating on a fresh install ed. CHANNELS, RECORDING_LENGTH, ... simplify
- Fix: PrivacyThreshold now works as intended
- Support for 'Species range model V2.4 - V2'
- **Experimental support** for automatic updates of location utilizing gpsd service. It requires GPS device (USB looger, modem with GNSS capabilities) to be connected and configured in gpsd.

!! note: see 'Migrating' on how to migrate from mcguirepr89

Expand Down
4 changes: 4 additions & 0 deletions homepage/views.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ function copyOutput(elem) {
'sudo systemctl restart spectrogram_viewer.service',
'sudo systemctl disable --now spectrogram_viewer.service',
'sudo systemctl enable --now spectrogram_viewer.service',
'sudo systemctl stop location_autoupdate.service',
'sudo systemctl restart location_autoupdate.service',
'sudo systemctl disable --now location_autoupdate.service',
'sudo systemctl enable --now location_autoupdate.service',
'sudo systemctl enable '.get_service_mount_name().' && sudo reboot',
'sudo systemctl disable '.get_service_mount_name().' && sudo reboot',
'stop_core_services.sh',
Expand Down
2 changes: 1 addition & 1 deletion newinstaller.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export HOME=$HOME
export USER=$USER

PACKAGES_MISSING=
for cmd in git jq ; do
for cmd in git jq gpsd; do
if ! which $cmd &> /dev/null;then
PACKAGES_MISSING="${PACKAGES_MISSING} $cmd"
fi
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ altair<5
inotify
requests
matplotlib
gpsdclient
apscheduler
24 changes: 24 additions & 0 deletions scripts/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ function syslog_shell_exec($cmd, $sudo_user = null) {
if(isset($_GET["latitude"])){
$latitude = $_GET["latitude"];
$longitude = $_GET["longitude"];
$location_autoupdate = $_GET["location_autoupdate"];
$location_autoupdate_interval = $_GET["location_autoupdate_interval"];
$location_autoupdate_threshold = $_GET["location_autoupdate_threshold"];
$site_name = $_GET["site_name"];
$site_name = str_replace('"', "", $site_name);
$site_name = str_replace('\'', "", $site_name);
Expand Down Expand Up @@ -145,6 +148,9 @@ function() {
$contents = preg_replace("/SITE_NAME=.*/", "SITE_NAME=\"$site_name\"", $contents);
$contents = preg_replace("/LATITUDE=.*/", "LATITUDE=$latitude", $contents);
$contents = preg_replace("/LONGITUDE=.*/", "LONGITUDE=$longitude", $contents);
$contents = preg_replace("/LOCATION_AUTOUPDATE=.*/", "LOCATION_AUTOUPDATE=$location_autoupdate", $contents);
$contents = preg_replace("/LOCATION_AUTOUPDATE_INTERVAL=.*/", "LOCATION_AUTOUPDATE_INTERVAL=$location_autoupdate_interval", $contents);
$contents = preg_replace("/LOCATION_AUTOUPDATE_THRESHOLD=.*/", "LOCATION_AUTOUPDATE_THRESHOLD=$location_autoupdate_threshold", $contents);
$contents = preg_replace("/BIRDWEATHER_ID=.*/", "BIRDWEATHER_ID=$birdweather_id", $contents);
$contents = preg_replace("/APPRISE_NOTIFICATION_TITLE=.*/", "APPRISE_NOTIFICATION_TITLE=\"$apprise_notification_title\"", $contents);
$contents = preg_replace("/APPRISE_NOTIFICATION_BODY=.*/", "APPRISE_NOTIFICATION_BODY=\"$apprise_notification_body\"", $contents);
Expand Down Expand Up @@ -458,8 +464,26 @@ function runProcess() {
<td><input name="longitude" type="number" style="width:6em;" max="180" min="-180" step="0.0001" value="<?php print($config['LONGITUDE']);?>" required/></td>
<td></td>
</tr>
<tr>
<td><label for="location_autoupdate">Location autoupdate: </label></td>
<td><input name="location_autoupdate" type="number" style="width:6em;" max="1" min="0" step="1" value="<?php print($config['LOCATION_AUTOUPDATE']);?>" required/></td>
<td></td>
</tr>
<tr>
<td><label for="location_autoupdate_interval">Location autoupdate interval: </label></td>
<td><input name="location_autoupdate_interval" type="number" style="width:6em;" max="86400" min="0" step="1" value="<?php print($config['LOCATION_AUTOUPDATE_INTERVAL']);?>" required/></td>
<td></td>
</tr>
<tr>
<td><label for="location_autoupdate_threshold">Location autoupdate threshold: </label></td>
<td><input name="location_autoupdate_threshold" type="number" style="width:6em;" max="90" min="0" step="0.0001" value="<?php print($config['LOCATION_AUTOUPDATE_THRESHOLD']);?>" required/></td>
<td></td>
</tr>
</table>
<p>Set your Latitude and Longitude to 4 decimal places. Get your coordinates <a href="https://latlong.net" target="_blank">here</a>.</p>
<p>Location autoupdate enables BirdNET-Pi to update its position from GPS device (via gpsd service).</p>
<p>Location autoupdate interval is set in seconds.</p>
<p>Location autoupdate threshold sets sensitivity for location changes, this way small fluctuations will be ingored.</p>
</td></tr></table><br>
<table class="settingstable"><tr><td>
<h2>BirdWeather</h2>
Expand Down
9 changes: 8 additions & 1 deletion scripts/install_config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,17 @@ SITE_NAME="$HOSTNAME"
## TO BE CHANGED TO STATIC VALUES
## Please only go to 4 decimal places. Example:43.3984


LATITUDE=$LATITUDE
LONGITUDE=$LONGITUDE

#--------------------- Experimental: location autoupdate ---------------------#

## This is an experiment to create service for updating location from locally
## running gpsd daemon, requires supported GPS device to be attached.
LOCATION_AUTOUPDATE=0
LOCATION_AUTOUPDATE_INTERVAL=300
LOCATION_AUTOUPDATE_THRESHOLD=0.0002

#--------------------------------- Model --------------------------------------#
#_____________The variable below configures which BirdNET model is_____________#
#______________________used for detecting bird audio.__________________________#
Expand Down
17 changes: 17 additions & 0 deletions scripts/install_services.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,22 @@ EOF
systemctl enable birdnet_analysis.service
}

install_location_autoupdate_service() {
cat << EOF > $HOME/BirdNET-Pi/templates/location_autoupdate.service
[Unit]
Description=The gpsd based location autoupdate for BirdNET
[Service]
Restart=no
Type=simple
User=${USER}
ExecStart=$PYTHON_VIRTUAL_ENV /usr/local/bin/location_autoupdate.py
[Install]
WantedBy=multi-user.target
EOF
ln -sf $HOME/BirdNET-Pi/templates/location_autoupdate.service /usr/lib/systemd/system
}
export -f install_location_autoupdate_service

create_necessary_dirs() {
echo "Creating necessary directories"
[ -d ${EXTRACTED} ] || sudo -u ${USER} mkdir -p ${EXTRACTED}
Expand Down Expand Up @@ -420,6 +436,7 @@ install_services() {
install_cleanup_cron
install_weekly_cron
increase_caddy_timeout
install_location_autoupdate_service # But does not enable, as it's experimental feature

create_necessary_dirs
generate_BirdDB
Expand Down
86 changes: 86 additions & 0 deletions scripts/location_autoupdate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""This module gets location from gpsd daemon and updates configuration if needed."""
import logging
import sys

from apscheduler.schedulers.background import BlockingScheduler
import gpsdclient
from utils.helpers import get_settings, _load_settings, write_settings

log = logging.getLogger(__name__)

def main():
"""Starting the location updates at given interval."""
conf = get_settings()

if(conf.getint('LOCATION_AUTOUPDATE') == 1):
log.info("Starting location autoupdate service")
scheduler = BlockingScheduler()
scheduler.add_job(location_update,'interval',seconds=conf.getint('LOCATION_AUTOUPDATE_INTERVAL'))
scheduler.start()
else:
log.info("Location autoupdate service is not enabled in birdnet.conf. Not starting.")

def location_update():
"""Gets location from gpsd and updates configuration if needed."""
_load_settings('/etc/birdnet/birdnet.conf',True)
conf = get_settings()
currentlatitude = conf.getfloat('LATITUDE')
currentlongitude = conf.getfloat('LONGITUDE')

threshold=conf.getfloat('LOCATION_AUTOUPDATE_THRESHOLD')
with gpsdclient.GPSDClient(host="127.0.0.1") as client:
for result in client.dict_stream(convert_datetime=True, filter=["TPV"]):
lat = result.get("lat", "n/a")
lon = result.get("lon", "n/a")
if(lat != "n/a" and lon != "n/a"):
break

newlatitude=round(lat,4)
newlongitude=round(lon,4)

latdiff = abs(currentlatitude - newlatitude)
londiff = abs(currentlongitude - newlongitude)

if((latdiff > threshold) or (londiff > threshold)):
log.info("New location detected: %s, %s",newlatitude,newlongitude)
lat2replace = "LATITUDE="+str(currentlatitude)
lon2replace = "LONGITUDE="+str(currentlongitude)
lat2replacewith = "LATITUDE="+str(newlatitude)
lon2replacewith = "LONGITUDE="+str(newlongitude)

try:
with open('/etc/birdnet/birdnet.conf', 'r') as configfile:
configuration = configfile.read()
configuration = configuration.replace(lat2replace,lat2replacewith)
configuration = configuration.replace(lon2replace,lon2replacewith)
configfile.close()
except Exception as e:
log.error("Error occured while trying to read configuration: ", e)

try:
with open('/etc/birdnet/birdnet.conf', 'w') as configfile:
configfile.write(configuration)
configfile.flush()
configfile.close()
except Exception as e:
log.error("Error occured while trying to write configuration: ", e)

_load_settings('/etc/birdnet/birdnet.conf',True)
write_settings()


def setup_logging():
"""Do logging in a nice and polite way."""
logger = logging.getLogger()
formatter = logging.Formatter("[%(name)s][%(levelname)s] %(message)s")
handler = logging.StreamHandler(stream=sys.stdout)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
global log
log = logging.getLogger('location_autoupdater')


if __name__ == '__main__':
setup_logging()
main()
1 change: 1 addition & 0 deletions scripts/restart_services.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ my_dir=$HOME/BirdNET-Pi/scripts
sudo systemctl stop birdnet_recording.service

services=(chart_viewer.service
location_autoupdate.service
spectrogram_viewer.service
icecast2.service
birdnet_recording.service
Expand Down
8 changes: 8 additions & 0 deletions scripts/service_controls.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ function service_status($name) {
<button type="submit" name="submit" <?php do_service_mount("disable");?> onclick="return confirm('This will reboot, are you sure?')">Disable</button>
<button type="submit" name="submit" <?php do_service_mount("enable");?> onclick="return confirm('This will reboot, are you sure?')">Enable</button>
</div>
<h3>Location Autoupdate (!experimental!) <?php echo service_status("location_autoupdate.service");?></h3>
<div role="group" class="btn-group-center">
<button type="submit" name="submit" value="sudo systemctl stop location_autoupdate.service">Stop</button>
<button type="submit" name="submit" value="sudo systemctl restart location_autoupdate.service">Restart</button>
<button type="submit" name="submit" value="sudo systemctl disable --now location_autoupdate.service">Disable</button>
<button type="submit" name="submit" value="sudo systemctl enable --now location_autoupdate.service">Enable</button>
</div>

<div role="group" class="btn-group-center">
<button type="submit" name="submit" value="stop_core_services.sh">Stop Core Services</button>
</div>
Expand Down
20 changes: 20 additions & 0 deletions scripts/update_birdnet_snippets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,26 @@ if ! [ -L /etc/avahi/services/http.service ];then
systemctl restart avahi-daemon.service
fi

# Add location autoupdate service if it ain't there
if ! [ -f $HOME/BirdNET-Pi/templates/location_autoupdate.service ];then
sudo_with_user $HOME/BirdNET-Pi/birdnet/bin/pip3 install gpsdclient
sudo_with_user $HOME/BirdNET-Pi/birdnet/bin/pip3 install apscheduler
export PYTHON_VIRTUAL_ENV="$HOME/BirdNET-Pi/birdnet/bin/python3"
cat << EOF > $HOME/BirdNET-Pi/templates/location_autoupdate.service
[Unit]
Description=The gpsd based location autoupdate for BirdNET
[Service]
Restart=no
Type=simple
User=${USER}
ExecStart=$PYTHON_VIRTUAL_ENV /usr/local/bin/location_autoupdate.py
[Install]
WantedBy=multi-user.target
EOF
sudo -E chown $USER:$USER $HOME/BirdNET-Pi/templates/location_autoupdate.service
ln -sf $HOME/BirdNET-Pi/templates/location_autoupdate.service /usr/lib/systemd/system
fi

if [ -L /usr/local/bin/analyze.py ];then
rm -f /usr/local/bin/analyze.py
fi
Expand Down