Set new Base version

master
git 2021-03-22 21:23:14 +01:00
commit 4e95570fbc
6 changed files with 354 additions and 0 deletions

79
.gitignore vendored Normal file
View File

@ -0,0 +1,79 @@
# Created by .ignore support plugin (hsz.mobi)
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
*.manifest
*.spec
pip-log.txt
pip-delete-this-directory.txt
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
*.mo
*.pot
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
instance/
.webassets-cache
.scrapy
docs/_build/
.pybuilder/
target/
.ipynb_checkpoints
profile_default/
ipython_config.py
__pypackages__/
celerybeat-schedule
celerybeat.pid
*.sage.py
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
.spyderproject
.spyproject
.ropeproject
/site
.mypy_cache/
.dmypy.json
dmypy.json
.pyre/
.pytype/
cython_debug/
/src/config.ini
/.idea/
/venv/

9
Dockerfile Normal file
View File

@ -0,0 +1,9 @@
FROM python:3-alpine
COPY . /code/
RUN pip install -r /code/requirements.txt
WORKDIR /code/src/
CMD ["python","app.py"]

62
README.md Normal file
View File

@ -0,0 +1,62 @@
# PiSwitch_Reporting
reporting server/API for the [PiSwitch](https://git.dennisvandermeulen.nl/dennis/PiSwitch)
## Installation Process
Clone the repository
```shell
git clone https://git.dennisvandermeulen.nl/dennis/PiSwitch_reporting.git
cd PiSwitch_reporting/
```
Setup virtual environment & install requirements (skip if you use Docker)
```shell
python3 -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
```
Setup config.ini
```shell
nano src/config.ini
```
setup database config
```ini
[database]
host =
user =
password =
db =
```
setup apikey for this server
```ini
[setup]
apikey = string
````
##Docker
use the included Dockerfile
```shell
docker run . -t piswitch/reporting -d -p 5000:5000
```
or build the dockerfile for use with [PiSwitch_frontend](https://git.dennisvandermeulen.nl/dennis/PiSwitch_frontend)
```shell
docker build . -t piswitch/reporting
```
## Systemd
Use the following script to automatically start the scripts at boot
````ini
[Unit]
Description=PiSwitch Reporting server
After=multi-user.target
[Service]
Type=simple
User=
Group=
WorkingDirectory=/path/to/PiSwitch_reporting/src
ExecStart=/path/to/venv/bin/python3 path/to/PiSwitch_reporting/src/server.py
[Install]
WantedBy=multi-user.target
````
save as PiSwitch_reporting.service

13
requirements.txt Normal file
View File

@ -0,0 +1,13 @@
astral==2.2
click==7.1.2
configparser==5.0.0
Flask==1.1.2
Flask-Cors==3.0.9
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
mysql-connector-python==8.0.23
protobuf==3.15.6
pytz==2020.1
six==1.15.0
Werkzeug==1.0.1

98
src/app.py Normal file
View File

@ -0,0 +1,98 @@
from flask import Flask, request, jsonify
from flask_cors import CORS
import configparser
from helper import storecmd, getcmd, updatestatus, getstatus, getalldata, updatelocation, getdbtime, datelookup
import datetime
app = Flask(__name__)
CORS(app)
def verifyapikey(requestapikey):
if requestapikey == apiKey:
return True
return False
@app.route('/cmd', methods=['POST', 'GET'])
def command():
if verifyapikey(request.values.get('apikey')):
if request.method == 'POST':
storecmd(request.values.get('id'), datetime.datetime.now(), request.values.get('response'))
return jsonify(response='success'), 200
else:
results = getcmd(request.values.get('id'))
x = 0
response = {}
for i in results:
response[x] = {'date': i[0], 'command': i[1]}
x = x + 1
return response, 200
return jsonify(response='invalid api key'), 401
@app.route('/status', methods=['POST', 'GET'])
def status():
if verifyapikey(request.values.get('apikey')):
if request.method == 'POST':
updatestatus(request.values.get('id'), datetime.datetime.now(), request.values.get('key'),
request.values.get('value'))
return jsonify(response='success'), 200
else:
result = getstatus(request.values.get('id'), request.values.get('key'))
return jsonify(response=result[0]), 200
return jsonify(response='invalid api key'), 401
@app.route('/gettime', methods=['POST'])
def gettime():
if verifyapikey(request.values.get('apikey')):
result = getdbtime(request.values.get('id'), request.values.get('key'))
return jsonify(response=str(result[0])), 200
return jsonify(response='invalid api key'), 401
@app.route('/fullstatus', methods=['POST'])
def fullstatus():
if verifyapikey(request.values.get('apikey')):
result = getalldata(request.values.get('id'))
return {'switch_name': result[1],
'switch_status': result[3],
'astral_status': result[4],
'conn_status': result[5],
'last_updated': result[2],
'on_time': str(result[6]),
'off_time': str(result[7]),
'loc_name': result[8],
'loc_region': result[9],
'loc_lat': result[10],
'loc_lon': result[11],
'loc_timezone': result[12],
'apikey': result[13]
}, 200
return jsonify(response='invalid api key'), 401
@app.route('/updatelocation', methods=['POST'])
def updateloc():
if verifyapikey(request.values.get('apikey')):
updatelocation(request.values.get('id'), datetime.datetime.now(), request.values.get('loc_name'),
request.values.get('loc_region'), request.values.get('loc_lat'), request.values.get('loc_lon'))
return jsonify(response='success'), 200
return jsonify(response='invalid api key'), 401
@app.route('/datelookup', methods=['POST'])
def lookupdate():
if verifyapikey(request.values.get('apikey')):
result = datelookup(request.values.get('id'),
request.values.get('day'), request.values.get('month'), request.values.get('year'))
return jsonify(response=result), 200
return jsonify(response='invalid api key'), 401
if __name__ == '__main__':
config = configparser.ConfigParser()
config.read('config.ini')
apiKey = config['setup']['apikey']
app.run(host='0.0.0.0')

93
src/helper.py Normal file
View File

@ -0,0 +1,93 @@
import mysql.connector
import configparser
import astral
import astral.sun
import datetime
config = configparser.ConfigParser()
config.read('config.ini')
host = config['database']['host']
user = config['database']['user']
password = config['database']['password']
db = config['database']['db']
def storecmd(device_id, date_time, command):
dwh = mysql.connector.connect(host=host,user=user,password=password,database=db)
c = dwh.cursor()
c.execute("""INSERT INTO commands(device_id,date_time,command) VALUES(%s,%s,%s)""", (device_id, date_time, command))
dwh.commit()
c.close()
def getcmd(device_id):
dwh = mysql.connector.connect(host=host,user=user,password=password,database=db)
c = dwh.cursor()
c.execute("""SELECT date_time, command FROM commands WHERE device_id = %s ORDER BY date_time DESC LIMIT 10 """,
(device_id,))
result = c.fetchmany(10)
c.close()
return result
def updatestatus(device_id, date_time, key, value):
if key in ['device_id', 'name', 'last_updated', 'switch_status', 'astral_status', 'conn_status', 'on_time',
'off_time', 'loc_name', 'loc_region', 'loc_lat', 'loc_lon', 'loc_timezone', 'apikey']:
dwh = mysql.connector.connect(host=host,user=user,password=password,database=db)
c = dwh.cursor()
c.execute("""UPDATE status SET last_updated = %s, {} = %s WHERE device_id = %s""".format(key),
(date_time, value, device_id))
dwh.commit()
c.close()
def getstatus(device_id, key):
dwh = mysql.connector.connect(host=host,user=user,password=password,database=db)
c = dwh.cursor()
c.execute("""SELECT {} FROM status WHERE device_id = %s""".format(key), ([device_id]))
result = c.fetchone()
c.close()
return result
def getalldata(device_id):
dwh = mysql.connector.connect(host=host,user=user,password=password,database=db)
c = dwh.cursor()
c.execute("""SELECT * FROM status WHERE device_id = %s""", ([device_id]))
result = c.fetchone()
c.close()
return result
def updatelocation(device_id, date_time, loc_name, loc_region, loc_lat, loc_lon):
dwh = mysql.connector.connect(host=host,user=user,password=password,database=db)
c = dwh.cursor()
c.execute(
"""UPDATE status SET last_updated = %s, loc_name = %s, loc_region = %s, loc_lat = %s, loc_lon = %s WHERE device_id = %s""",
(date_time, loc_name, loc_region, loc_lat, loc_lon, device_id))
dwh.commit()
c.close()
def getdbtime(device_id, key):
if key in ['device_id', 'name', 'last_updated', 'switch_status', 'astral_status', 'conn_status', 'on_time',
'off_time', 'loc_name', 'loc_region', 'loc_lat', 'loc_lon', 'loc_timezone', 'apikey']:
dwh = mysql.connector.connect(host=host,user=user,password=password,database=db)
c = dwh.cursor()
c.execute("""SELECT {} FROM status WHERE device_id = %s""".format(key), ([device_id]))
result = c.fetchone()
c.close()
return result
def datelookup(device_id, day, month, year):
dwh = mysql.connector.connect(host=host,user=user,password=password,database=db)
c = dwh.cursor()
c.execute("""SELECT loc_name, loc_region, loc_lat, loc_lon, loc_timezone FROM status WHERE device_id = %s""",
(device_id,))
result = c.fetchone()
c.close()
l = astral.LocationInfo(name=result[0], region=result[1], latitude=result[2], longitude=result[3],
timezone=result[4])
triggerontime = astral.sun.sunset(observer=l.observer, date=datetime.date(day, month, year))
return triggerontime