From b2597687e36661f62c44099c066ed4d033109b90 Mon Sep 17 00:00:00 2001 From: "pi@rpi-7aea.20221209" Date: Sat, 10 Dec 2022 15:25:08 +0100 Subject: [PATCH] Added simplistic webserver --- sem-6000-web.md | 29 ++++++++++++++ sem-6000-web.py | 95 ++++++++++++++++++++++++++++++++++++++++++++ sem-6000-web.service | 11 +++++ 3 files changed, 135 insertions(+) create mode 100644 sem-6000-web.md create mode 100755 sem-6000-web.py create mode 100644 sem-6000-web.service diff --git a/sem-6000-web.md b/sem-6000-web.md new file mode 100644 index 0000000..7ff1d47 --- /dev/null +++ b/sem-6000-web.md @@ -0,0 +1,29 @@ +# Simple Webfrontend +_"Simplistic python/flask wrapper for the _sem-6000.exp_ command"_ + +This little webserver lets you control your known (`.known_sem6`) devices through a browser. + +## Getting started +Install flask and yattag python modules. +``` +sudo pip3 install flask yattag +``` + +## Check functionality +Start the service once. +``` +$ python3 ./sem-6000-web.py +``` +Access via _http://IP:5000_ + +## Register as Service +Register as SystemD service at bootup. +``` +sudo systemctl enable --now "$(pwd)/sem-6000-web.service" +``` + +Check the status and logs. +``` +systemctl status sem-6000-web +journalctl -f -u sem-6000-web +``` diff --git a/sem-6000-web.py b/sem-6000-web.py new file mode 100755 index 0000000..d881ff4 --- /dev/null +++ b/sem-6000-web.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os, subprocess +from flask import Flask, request, Response, abort +from yattag import Doc + + +# learn known devices +devices = [] +with open(os.path.expanduser("~/.known_sem6"), 'r') as f: + for line in f.readlines(): + devices.append(line.strip().split(' ')[-1]) + +actions = [ 'on', 'off', 'toggle', 'status' ] + + +def run_command(command): + """ execute the given command, return it's std-out and -err""" + result = subprocess.run(command.split(' '), stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out = result.stdout.decode('utf-8'); err = result.stderr.decode('utf-8') + out = F"{command}{os.linesep}{out}" + if err != '': + out = F"{out}{os.linesep}{err}" + return out + + +# flask application starts here +app = Flask(__name__) + +@app.route('/sem//', methods=["GET", "POST"]) +def handle_sem(device): + """ run this when '/sem//?action=' was accessed """ + # verfiy parameters + if device not in devices: + return abort(404, F"device '{device}' unknown") + + action = request.args.get('action') # parse GET or POST arguments to identify 'action' parameter + if request.environ['REQUEST_METHOD'] == 'POST': + action = request.form['action'] + + if action is None: + action = 'status' + + if action not in actions: + return abort(404, F"action '{action}' unknown") + + # start assembly of page + doc, tag, text = Doc().tagtext() + with tag('title'): + text(device) + + # if request was anything than 'status' redirect back to status + if action != 'status': + doc.asis(F"") + + # add buttons at the top of page + with tag('form', method='get', action=request.environ['PATH_INFO']): + with tag('table', border='0', style="text-align:center;"): + for a in actions: + with tag('td'): + with tag('input', type='submit', name='action', value=a): + pass + + # add section with output of command + with tag('hr'): + with tag('pre'): + # assemble and run command + text(run_command(F"./sem-6000.exp {device} --{action} --print")) + with tag('hr'): + pass + + # render and return page + return Response(doc.getvalue(), mimetype='text/html;charset=UTF-8') + + +@app.route('/', methods=["GET"]) +def handle_root(): + """ run this when '/' was accessed """ + # start assembly of page + doc, tag, text = Doc().tagtext() + with tag('h1'): + text('known SEM-6000 devices') + + for device in devices: + with tag('h2'): + with tag('a', href=F"/sem/{device}/"): text(F"Device {device}") + + # render and return page + return Response(doc.getvalue(), mimetype='text/html;charset=UTF-8') + + +if __name__ == "__main__": + app.run(debug=False, host='0.0.0.0', port=5000) + diff --git a/sem-6000-web.service b/sem-6000-web.service new file mode 100644 index 0000000..9574523 --- /dev/null +++ b/sem-6000-web.service @@ -0,0 +1,11 @@ +[Unit] +Description=voltcraft sem-6000 web control +After=bluetooth.target + +[Service] +User=pi +WorkingDirectory=/home/pi/voltcraft-sem-6000 +ExecStart=/usr/bin/python3 sem-6000-web.py + +[Install] +WantedBy=multi-user.target