From 195c06a1c9be879997447390628c814dfd2a9f83 Mon Sep 17 00:00:00 2001 From: manzari Date: Sat, 22 Dec 2018 02:08:29 +0100 Subject: [PATCH] Initial commit --- .gitignore | 7 ++++ README.md | 28 +++++++++++++++ install/gunicorn.service | 17 +++++++++ install/install.sh | 26 ++++++++++++++ install/nginx.conf | 24 +++++++++++++ install/requirements.txt | 4 +++ raspotify-monitor.py | 75 +++++++++++++++++++++++++++++++++++++++ screenshot.png | Bin 0 -> 24668 bytes templates/status.html | 74 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 255 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 install/gunicorn.service create mode 100644 install/install.sh create mode 100644 install/nginx.conf create mode 100644 install/requirements.txt create mode 100644 raspotify-monitor.py create mode 100644 screenshot.png create mode 100644 templates/status.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8192da1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +### PyCharm ### +.idea/ + +### Python ### +venv/ +__pycache__/ +*.pyc \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e3617c8 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +# Raspotify Status +A simple monitoring app for the awesome [raspotify client](https://github.com/dtcooper/raspotify) on raspbian + +![](/screenshot.png?raw=true) + +## Installation +### Fast +Open a new ssh session to the raspotify host and navigate to your home directory then run the following command +```bash +wget -qO- https://github.com/manzari/raspotify-monitor/raw/master/install/install.sh | bash +``` +### Manual +#### Requirements +```bash +sudo apt-get install -y python3-pip nginx +sudo -H pip3 install -r requirements.txt +``` +#### Copy config files +```bash +sudo cp nginx.conf /etc/nginx/nginx.conf +sudo cp gunicorn.service /etc/systemd/system/gunicorn.service +``` +#### Start the services +```bash +sudo systemctl daemon-reload +sudo service gunicorn start +sudo service nginx start +``` \ No newline at end of file diff --git a/install/gunicorn.service b/install/gunicorn.service new file mode 100644 index 0000000..794f83c --- /dev/null +++ b/install/gunicorn.service @@ -0,0 +1,17 @@ +[Unit] +Description=gunicorn daemon for raspotify-monitor +After=network.target + +[Service] +PIDFile=/run/gunicorn/pid +User=pi +Group=pi +RuntimeDirectory=/home/pi/raspotify-monitor +WorkingDirectory=/home/pi/raspotify-monitor +ExecStart=/usr/bin/sudo gunicorn --bind 127.0.0.1:8000 raspotify-monitor:app +ExecReload=/bin/kill -s HUP $MAINPID +ExecStop=/bin/kill -s TERM $MAINPID +PrivateTmp=true + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/install/install.sh b/install/install.sh new file mode 100644 index 0000000..dc0c2a1 --- /dev/null +++ b/install/install.sh @@ -0,0 +1,26 @@ +#!/usr/bin/bash +sudo apt-get update +sudo apt-get install -y python3-pip nginx +if test "$PWD" = "/home/pi"; then + if test -d /home/pi/raspotify-monitor; then + sudo service gunicorn stop + sudo service nginx stop + sudo rm -r /home/pi/raspotify-monitor + fi + echo downloading repo... >&2 + wget https://github.com/manzari/raspotify-monitor/archive/master.zip + unzip master.zip + rm master.zip + mv raspotify-monitor-master raspotify-monitor +else + echo ERROR: must be executed in /home/pi >&2 + exit 1 +fi +sudo -H pip3 install -r raspotify-monitor/install/requirements.txt +sudo cp raspotify-monitor/install/nginx.conf /etc/nginx/nginx.conf +sudo cp raspotify-monitor/install/gunicorn.service /etc/systemd/system/gunicorn.service +sudo systemctl daemon-reload +sudo service gunicorn start +sudo service nginx start +echo done! >&2 +exit 0 \ No newline at end of file diff --git a/install/nginx.conf b/install/nginx.conf new file mode 100644 index 0000000..645c5d2 --- /dev/null +++ b/install/nginx.conf @@ -0,0 +1,24 @@ +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + server { + listen 80; + server_name raspotify.fritz.box; + location / { + proxy_pass http://127.0.0.1:8000/; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + } +} diff --git a/install/requirements.txt b/install/requirements.txt new file mode 100644 index 0000000..253284e --- /dev/null +++ b/install/requirements.txt @@ -0,0 +1,4 @@ +Flask +jinja2 +gunicorn + diff --git a/raspotify-monitor.py b/raspotify-monitor.py new file mode 100644 index 0000000..d8a8a03 --- /dev/null +++ b/raspotify-monitor.py @@ -0,0 +1,75 @@ +from flask import Flask, redirect +from jinja2 import Template +from subprocess import getoutput +import re + +app = Flask(__name__) +status_template = Template(open('templates/status.html', 'r').read()) + + +def refresh_status(): + stdout = getoutput("sudo netstat -anpt | awk '((/LISTEN/||/ESTABLISHED/)&&/librespot/)||/Program/{;print $0}'") + stati = {'run': False, 'listen': False, 'established': False, 'statuslines': []} + if re.search(r"(LISTEN\s+\d+\/librespot)", stdout, re.MULTILINE): + stati['listen'] = True + if re.search(r"(ESTABLISHED\s+\d+\/librespot)", stdout, re.MULTILINE): + stati['established'] = True + stdout2 = getoutput("sudo service raspotify status") + stati['statuslines'] = stdout2.split('\n') + if re.search(r"(Active:\sactive\s\(running\))", stdout2, re.MULTILINE): + stati['run'] = True + return stati + + +def control_service(task): + stdout = getoutput("sudo service raspotify " + task) + return stdout + + +@app.route('/') +def home(): + return redirect("/status", code=301) + + +@app.route('/status') +def status(): + print("STATUS CALLED") + stati = refresh_status() + return status_template.render( + listenstatus=stati['listen'], + establishedstatus=stati['established'], + runstatus=stati['run'], + statuslines=stati['statuslines'][:5], + refreshtime=7 + ) + + +@app.route('/restart') +def restart(): + output = control_service('restart') + if output == '': + return 'OK' + else: + return 'ERROR' + + +@app.route('/start') +def start(): + output = control_service('start') + if output == '': + return 'OK' + else: + return 'ERROR' + + +@app.route('/stop') +def stop(): + output = control_service('stop') + if output == '': + return 'OK' + else: + return 'ERROR' + + +if __name__ == '__main__': + app.run() diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..8dc86326c4a619e543031e202790976616e11108 GIT binary patch literal 24668 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 + + + + + RaspotifyStatus + + + + + +
+
+

{% if runstatus %}✔{% else %}❌{% endif %}Service Running

+

{% if listenstatus %}✔{% else %}❌{% endif %} Listening

+

{% if establishedstatus %}✔{% else %}❌{% endif %} Connection Established

+
+
+ + + +
+
+
+
    + {% for line in statuslines %} +
  • {{ line }}
  • + {% endfor %} +
+
+ + + \ No newline at end of file