2022-03-30 16:10:21 +02:00

228 lines
7.1 KiB
Python

"""Flask application for greenhouse"""
from datetime import datetime, timedelta
import json
import logging
import os
import sys
import xmlrpc.client
from flask import Flask
from flask import render_template
from flask import make_response
from flask import request
from flask import jsonify
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
LOG_LEVEL = logging.INFO
LOG_FILE = "/var/log/greenhouseui.log"
LOG_FORMAT = "%(asctime)s %(levelname)s %(message)s"
HOST = "localhost"
PORT = 64001
URL = f"http://{HOST}:{PORT}"
logging.basicConfig(format=LOG_FORMAT, level=LOG_LEVEL, filename=LOG_FILE)
# logging.basicConfig(format=LOG_FORMAT, level=LOG_LEVEL)
log = logging.getLogger()
def get_image_install_path():
"""Get the path where to install dynamically created images to"""
for path in sys.path:
try:
content = os.listdir(path)
if "greenhouseui" in content:
return os.path.join(path, "greenhouseui/static")
except FileNotFoundError:
pass
return None
def draw_temperature_image():
temperature_dates = []
temperatures = []
with open("/var/log/gardencontrol.log", "r", encoding="UTF-8") as logfile:
for line in logfile:
line = line.strip()
if "Temperature" in line:
chunks = line.split(" ")
logtime = chunks[0] + " " + chunks[1]
logtime = datetime.strptime(logtime, "%Y-%m-%d %H:%M:%S,%f")
now = datetime.now()
start_time = now - timedelta(hours=24)
if logtime >= start_time:
temperature_dates.append(logtime)
temperature = float(chunks[4])
temperatures.append(temperature)
background_color = "#282929"
color = "#b6b6b6"
fig, ax = plt.subplots(1)
fig.set_figwidth(4)
fig.set_figheight(2)
fig.set_facecolor(background_color)
ax.set_facecolor(background_color)
ax.tick_params(axis="x", colors = color)
ax.tick_params(axis="y", colors = color)
ax.spines["top"].set_visible(False)
ax.spines["left"].set_visible(False)
ax.spines["bottom"].set_visible(False)
ax.spines["right"].set_visible(False)
# ax.set_ylabel("°C", rotation=0)
ax.yaxis.label.set_color(color)
fig.autofmt_xdate()
plt.plot(temperature_dates, temperatures, color=color)
xfmt = mdates.DateFormatter('%H:%M')
ax.xaxis.set_major_formatter(xfmt)
path = get_image_install_path()
if path:
img_file = os.path.join(path, "greenhouse_temperature.png")
if os.path.exists(img_file):
os.remove(img_file)
plt.savefig(img_file)
plt.close("all")
app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
"""Handle GET to index.html"""
draw_temperature_image()
return render_template('index.html')
@app.route('/sample/<idx>', methods=['GET'])
def get_sample(idx='0'):
"""Handle GET to /sample/<idx>"""
idx = int(idx)
res = {}
client = xmlrpc.client.ServerProxy(URL)
if idx == 1:
heat = {}
heat['id'] = str(idx)
heat['state'] = client.get_current_heat_state(idx)
temp = client.get_current_temperature(idx)
if temp:
temperature = {}
temperature['id'] = str(idx)
temperature['value'] = temp
res['heat'] = heat
res['temperature'] = temperature
water = {}
water['id'] = str(idx)
water['state'] = client.get_current_water_state(idx)
res['water'] = water
return make_response(jsonify(res), 200)
@app.route('/config/<idx>', methods=['GET'])
def get_config(idx='0'):
"""Hadnle GET to config/<idx>"""
idx = int(idx)
res = {}
client = xmlrpc.client.ServerProxy(URL)
if idx == 1:
heat = {}
heat['id'] = str(idx)
heat['autostate'] = client.get_heat_autostate(idx)
heat['on_temperature'] = client.get_on_temperature(idx)
heat['off_temperature'] = client.get_off_temperature(idx)
res['heat'] = heat
water = {}
water['id'] = str(idx)
water['autostate'] = client.get_water_autostate(idx)
water['times'] = client.get_water_times(idx)
res['water'] = water
return make_response(jsonify(res), 200)
@app.route('/sample', methods=['PATCH'])
def patch_sample():
"""Handle PATCH to /sample"""
client = xmlrpc.client.ServerProxy(URL)
record = json.loads(request.data)
if 'id' in record and record['id'] == '1':
if 'heatstate' in record:
if record['heatstate']:
client.set_heat_state(record['id'])
else:
client.clear_heat_state(record['id'])
if 'id' in record and 'waterstate' in record:
if record['waterstate']:
client.set_water_state(record['id'])
else:
client.clear_water_state(record['id'])
return make_response("", 204)
@app.route('/config', methods=['PATCH'])
def patch_config():
"""Handle PATCH to /config"""
client = xmlrpc.client.ServerProxy(URL)
record = json.loads(request.data)
if 'water' in record:
water = record['water']
if 'autostate' in water:
if water['autostate']:
client.set_water_autostate(water['id'])
else:
client.clear_water_autostate(water['id'])
if 'times' in water:
client.set_water_times(water['id'], water['times'])
if 'heat' in record:
if 'id' in record['heat'] and record['heat']['id'] == '1':
if 'autostate' in record['heat']:
if record['heat']['autostate']:
client.set_heat_autostate('1')
else:
client.clear_heat_autostate('1')
if 'increase_on_temperature' in record['heat']:
if record['heat']['increase_on_temperature']:
client.increase_on_temperature('1')
if 'decrease_on_temperature' in record['heat']:
if record['heat']['decrease_on_temperature']:
client.decrease_on_temperature('1')
if 'increase_off_temperature' in record['heat']:
if record['heat']['increase_off_temperature']:
client.increase_off_temperature('1')
if 'decrease_off_temperature' in record['heat']:
if record['heat']['decrease_off_temperature']:
client.decrease_off_temperature('1')
# prepare answer
res = {}
if 'heat' in record and record['heat']['id'] == '1':
heat = {}
heat['id'] = '1'
heat['autostate'] = client.get_heat_autostate(1)
heat['on_temperature'] = client.get_on_temperature(1)
heat['off_temperature'] = client.get_off_temperature(1)
res['heat'] = heat
if 'water' in record:
water = {}
water['id'] = record['water']['id']
water['autostate'] = client.get_water_autostate(int(record['water']['id']))
water['times'] = client.get_water_times(int(record['water']['id']))
res['water'] = water
return make_response(jsonify(res), 200)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8000)