|
import flask |
|
from flask import request, jsonify |
|
import os |
|
import sqlite3 |
|
from datetime import datetime |
|
import matplotlib.pyplot as plt |
|
import io |
|
import base64 |
|
from dotenv import load_dotenv |
|
import globs |
|
from flask import render_template |
|
from api_logic import api |
|
load_dotenv() |
|
|
|
|
|
def init_db(db_name): |
|
conn = sqlite3.connect(db_name) |
|
cursor = conn.cursor() |
|
|
|
|
|
cursor.execute(''' |
|
CREATE TABLE IF NOT EXISTS system_data ( |
|
id INTEGER PRIMARY KEY AUTOINCREMENT, -- Автоинкрементный счётчик |
|
date_time TEXT, -- Дата и время |
|
dey TEXT, |
|
wek TEXT, |
|
v_hid TEXT, |
|
v_min TEXT, |
|
ph TEXT, |
|
ec TEXT, |
|
tS TEXT, |
|
tA TEXT, |
|
hDm TEXT, |
|
sVen TEXT, |
|
rFul TEXT, |
|
rLi TEXT, |
|
rWat TEXT, |
|
rRas TEXT, |
|
rPH TEXT, |
|
rEC TEXT, |
|
rSl TEXT, |
|
rLe TEXT, |
|
alW TEXT |
|
) |
|
''') |
|
|
|
conn.commit() |
|
conn.close() |
|
|
|
|
|
globs.dey = 0 |
|
globs.wek = 0 |
|
globs.v_hid = 0 |
|
globs.v_min = 0 |
|
globs.ph = 0 |
|
globs.ec = 0 |
|
globs.tS = 0 |
|
globs.tA = 0 |
|
globs.hDm = 0 |
|
globs.sVen = 0 |
|
globs.rFul = 0 |
|
globs.rLi = 0 |
|
globs.rWat = 0 |
|
globs.rRas = 0 |
|
globs.rPH = 0 |
|
globs.rEC = 0 |
|
globs.rSl = 0 |
|
globs.rLe = 0 |
|
globs.alW = 0 |
|
|
|
globs.ph_eep = 0 |
|
globs.ph_on_eep = 0 |
|
globs.ec_eep = 0 |
|
globs.ec_A_eep = 0 |
|
globs.ec_B_eep = 0 |
|
globs.ec_C_eep = 0 |
|
globs.l_ON_h_eep = 0 |
|
globs.l_ON_m_eep = 0 |
|
globs.l_OFF_h_eep = 0 |
|
globs.l_OFF_m_eep = 0 |
|
globs.t_Voz_eep = 0 |
|
|
|
|
|
app = flask.Flask(__name__, template_folder="./") |
|
app.config['DEBUG'] = True |
|
|
|
|
|
def save_data_to_db(db_name, data): |
|
try: |
|
conn = sqlite3.connect(db_name) |
|
cursor = conn.cursor() |
|
|
|
|
|
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') |
|
|
|
|
|
cursor.execute(''' |
|
INSERT INTO system_data ( |
|
date_time, dey, wek, v_hid, v_min, ph, ec, tS, tA, hDm, sVen, rFul, rLi, rWat, rRas, rPH, rEC, rSl, rLe, alW |
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) |
|
''', ( |
|
current_time, |
|
data['dey'], data['wek'], data['v_hid'], data['v_min'], data['ph'], data['ec'], |
|
data['tS'], data['tA'], data['hDm'], data['sVen'], data['rFul'], data['rLi'], |
|
data['rWat'], data['rRas'], data['rPH'], data['rEC'], data['rSl'], data['rLe'], data['alW'] |
|
)) |
|
|
|
conn.commit() |
|
conn.close() |
|
except Exception as e: |
|
return jsonify({'status': 'error', 'message': str(e)}), 500 |
|
|
|
|
|
@app.route('/sav_db_api', methods=['GET']) |
|
def sav_db_api(): |
|
|
|
init_db('system_data.db') |
|
|
|
|
|
data = { |
|
'dey': request.args.get('dey'), |
|
'wek': request.args.get('wek'), |
|
'v_hid': request.args.get('v_hid'), |
|
'v_min': request.args.get('v_min'), |
|
'ph': request.args.get('ph'), |
|
'ec': request.args.get('ec'), |
|
'tS': request.args.get('tS'), |
|
'tA': request.args.get('tA'), |
|
'hDm': request.args.get('hDm'), |
|
'sVen': request.args.get('sVen'), |
|
'rFul': request.args.get('rFul'), |
|
'rLi': request.args.get('rLi'), |
|
'rWat': request.args.get('rWat'), |
|
'rRas': request.args.get('rRas'), |
|
'rPH': request.args.get('rPH'), |
|
'rEC': request.args.get('rEC'), |
|
'rSl': request.args.get('rSl'), |
|
'rLe': request.args.get('rLe'), |
|
'alW': request.args.get('alW') |
|
} |
|
|
|
|
|
required_params = ['dey', 'wek', 'v_hid', 'v_min', 'ph', 'ec', 'tS', 'tA', 'hDm', 'sVen', 'rFul', 'rLi', 'rWat', 'rRas', 'rPH', 'rEC', 'rSl', 'rLe', 'alW'] |
|
for param in required_params: |
|
if data[param] is None: |
|
return jsonify({'status': 'error', 'message': f'Отсутствует параметр: {param}'}), 400 |
|
|
|
|
|
save_data_to_db('system_data.db', data) |
|
|
|
|
|
return jsonify({'status': 'success', 'message': 'Данные сохранены'}) |
|
|
|
|
|
@app.route('/get_all_data', methods=['GET']) |
|
def get_all_data(): |
|
try: |
|
conn = sqlite3.connect('system_data.db') |
|
cursor = conn.cursor() |
|
|
|
|
|
cursor.execute('SELECT * FROM system_data') |
|
rows = cursor.fetchall() |
|
|
|
|
|
column_names = [description[0] for description in cursor.description] |
|
|
|
|
|
data = [] |
|
for row in rows: |
|
data.append(dict(zip(column_names, row))) |
|
|
|
conn.close() |
|
|
|
|
|
return jsonify(data) |
|
except Exception as e: |
|
return jsonify({'status': 'error', 'message': str(e)}), 500 |
|
|
|
|
|
|
|
|
|
|
|
@app.route('/plot_ph', methods=['GET']) |
|
def plot_ph(): |
|
try: |
|
|
|
start_date = request.args.get('start_date') |
|
end_date = request.args.get('end_date') |
|
|
|
|
|
if start_date and end_date: |
|
try: |
|
|
|
start_date = datetime.strptime(start_date, '%Y-%m-%dT%H:%M') |
|
end_date = datetime.strptime(end_date, '%Y-%m-%dT%H:%M') |
|
|
|
|
|
if start_date >= end_date: |
|
return ''' |
|
<html> |
|
<body> |
|
<h1>Неправильная дата выбрана</h1> |
|
<p>Дата начала должна быть раньше даты окончания.</p> |
|
<button onclick="window.location.href='/plot_ph'">Новые данные</button> |
|
</body> |
|
</html> |
|
''' |
|
except ValueError: |
|
return ''' |
|
<html> |
|
<body> |
|
<h1>Неправильная дата выбрана</h1> |
|
<p>Формат даты должен быть YYYY-MM-DDTHH:MM.</p> |
|
<button onclick="window.location.href='/plot_ph'">Новые данные</button> |
|
</body> |
|
</html> |
|
''' |
|
|
|
|
|
conn = sqlite3.connect('system_data.db') |
|
cursor = conn.cursor() |
|
|
|
|
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='system_data'") |
|
table_exists = cursor.fetchone() |
|
|
|
if not table_exists: |
|
return ''' |
|
<html> |
|
<body> |
|
<h1>В базе данных отсутствуют значения</h1> |
|
<p>Таблица system_data не существует. Обновите базу данных.</p> |
|
<button onclick="window.location.href='/plot_ph'">Обновить базу данных</button> |
|
</body> |
|
</html> |
|
''' |
|
|
|
|
|
cursor.execute(''' |
|
SELECT date_time, ph, dey, wek |
|
FROM system_data |
|
WHERE date_time BETWEEN ? AND ? |
|
ORDER BY date_time |
|
''', (start_date, end_date)) |
|
rows = cursor.fetchall() |
|
|
|
conn.close() |
|
|
|
|
|
if not rows: |
|
return ''' |
|
<html> |
|
<body> |
|
<h1>Данные отсутствуют в базе данных</h1> |
|
<p>Для выбранного диапазона дат данные не найдены.</p> |
|
<button onclick="window.location.href='/plot_ph'">Новые данные</button> |
|
</body> |
|
</html> |
|
''' |
|
|
|
|
|
dates = [f"{row[0]} d: {row[2]} w: {row[3]}" for row in rows] |
|
ph_values = [float(row[1]) for row in rows] |
|
|
|
|
|
plt.figure(figsize=(15, 6)) |
|
plt.plot(dates, ph_values, marker='o', linestyle='-', color='b') |
|
plt.title('График значений pH') |
|
plt.xlabel('Дата и время') |
|
plt.ylabel('Значение pH') |
|
plt.xticks(rotation=90) |
|
plt.grid(True) |
|
plt.gcf().subplots_adjust(bottom=0.4) |
|
|
|
|
|
buffer = io.BytesIO() |
|
plt.savefig(buffer, format='png') |
|
buffer.seek(0) |
|
|
|
|
|
plot_data = base64.b64encode(buffer.getvalue()).decode('utf-8') |
|
|
|
|
|
return f''' |
|
<html> |
|
<body> |
|
<h1>График значений pH</h1> |
|
<button onclick="window.location.href='/plot_ph'">Новые данные</button> |
|
<button onclick="window.location.reload()">Обновить данные</button> |
|
<br><br> |
|
<img src="data:image/png;base64,{plot_data}" alt="График pH"> |
|
</body> |
|
</html> |
|
''' |
|
|
|
|
|
return ''' |
|
<html> |
|
<body> |
|
<h1>Выберите диапазон даты и времени для графика pH</h1> |
|
<form method="GET"> |
|
<label for="start_date">Начало:</label> |
|
<input type="datetime-local" id="start_date" name="start_date" required> |
|
<br><br> |
|
<label for="end_date">Конец:</label> |
|
<input type="datetime-local" id="end_date" name="end_date" required> |
|
<br><br> |
|
<button type="submit">Показать график</button> |
|
</form> |
|
</body> |
|
</html> |
|
''' |
|
except Exception as e: |
|
return jsonify({'status': 'error', 'message': str(e)}), 500 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route("/") |
|
def index(): |
|
return flask.render_template('index.html') |
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/online', methods=['GET']) |
|
def online(): |
|
return render_template('online.html') |
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/online_api', methods=['GET']) |
|
def online_api(): |
|
return jsonify(dey=globs.dey, |
|
wek=globs.wek, |
|
v_hid=globs.v_hid, |
|
v_min=globs.v_min, |
|
ph=globs.ph, |
|
ec=globs.ec, |
|
tS=globs.tS, |
|
tA=globs.tA, |
|
hDm=globs.hDm, |
|
sVen=globs.sVen, |
|
rFul=globs.rFul, |
|
rLi=globs.rLi, |
|
rWat=globs.rWat, |
|
rRas=globs.rRas, |
|
rPH=globs.rPH, |
|
rEC=globs.rEC, |
|
rSl=globs.rSl, |
|
rLe=globs.rLe, |
|
alW=globs.alW |
|
) |
|
|
|
|
|
|
|
|
|
|
|
@app.route('/settings', methods=['GET']) |
|
def settings(): |
|
return render_template('settings.html') |
|
|
|
|
|
@app.route('/settings_api', methods=['GET']) |
|
def settings_api(): |
|
return jsonify(ph_eep=globs.ph_eep, |
|
ph_on_eep=globs.ph_on_eep, |
|
ec_eep=globs.ec_eep, |
|
ec_A_eep=globs.ec_A_eep, |
|
ec_B_eep=globs.ec_B_eep, |
|
ec_C_eep=globs.ec_C_eep, |
|
l_ON_h_eep=globs.l_ON_h_eep, |
|
l_ON_m_eep=globs.l_ON_m_eep, |
|
l_OFF_h_eep=globs.l_OFF_h_eep, |
|
l_OFF_m_eep=globs.l_OFF_m_eep, |
|
t_Voz_eep=globs.t_Voz_eep |
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/pH_set', methods=['GET']) |
|
def set_pH_value(): |
|
ph_value = request.args.get('value') |
|
globs.ph_set = ph_value |
|
globs.eep_set = 1 |
|
return "pH value set successfully" |
|
|
|
|
|
@app.route('/ph_on_set', methods=['GET']) |
|
def ph_on_value(): |
|
ph_on_value = request.args.get('value') |
|
globs.ph_on_set = ph_on_value |
|
globs.eep_set = 2 |
|
return "EC value set successfully" |
|
|
|
|
|
|
|
@app.route('/EC_set', methods=['GET']) |
|
def set_EC_value(): |
|
ec_value = request.args.get('value') |
|
globs.ec_set = ec_value |
|
globs.eep_set = 3 |
|
return "EC value set successfully" |
|
|
|
@app.route('/ec_A_set', methods=['GET']) |
|
def ec_A_setValue(): |
|
ec_A_setValue = request.args.get('value') |
|
globs.ec_A_set = ec_A_setValue |
|
globs.eep_set = 4 |
|
return "EC value set successfully" |
|
|
|
@app.route('/ec_B_set', methods=['GET']) |
|
def ec_B_setValue(): |
|
ec_B_setValue = request.args.get('value') |
|
globs.ec_B_set = ec_B_setValue |
|
globs.eep_set = 5 |
|
return "EC value set successfully" |
|
|
|
@app.route('/ec_C_set', methods=['GET']) |
|
def ec_C_setValue(): |
|
ec_C_setValue = request.args.get('value') |
|
globs.ec_C_set = ec_C_setValue |
|
globs.eep_set = 6 |
|
return "EC value set successfully" |
|
|
|
|
|
@app.route('/l_ON_set', methods=['GET']) |
|
def l_ON_set(): |
|
globs.l_ON_h_set = request.args.get('l_ON_h_set') |
|
globs.l_ON_m_set = request.args.get('l_ON_m_set') |
|
globs.eep_set = 7 |
|
return "EC value set successfully" |
|
|
|
|
|
|
|
@app.route('/l_OFF_set', methods=['GET']) |
|
def l_OFF_set(): |
|
globs.l_OFF_h_set = request.args.get('l_OFF_h_set') |
|
globs.l_OFF_m_set = request.args.get('l_OFF_m_set') |
|
globs.eep_set = 8 |
|
return "EC value set successfully" |
|
|
|
|
|
|
|
|
|
@app.route('/t_Voz_eep_set', methods=['GET']) |
|
def t_Voz_eep_set(): |
|
t_Voz_eep_set = request.args.get('value') |
|
globs.ec_t_Voz_set = t_Voz_eep_set |
|
globs.eep_set = 9 |
|
return "EC value set successfully" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/but_start', methods=['GET']) |
|
def but_start(): |
|
globs.eep_set = 10 |
|
return jsonify(value_set="start") |
|
|
|
@app.route('/but_stop', methods=['GET']) |
|
def but_stop(): |
|
globs.eep_set = 11 |
|
return jsonify(value_set="stop") |
|
|
|
@app.route('/but_res', methods=['GET']) |
|
def but_res(): |
|
globs.eep_set = 12 |
|
return jsonify(value_set="res") |
|
|
|
@app.route('/but_sliv', methods=['GET']) |
|
def but_sliv(): |
|
globs.eep_set = 13 |
|
return jsonify(value_set="sliv") |
|
|
|
|
|
|
|
|
|
@app.route("/api", methods=['GET']) |
|
def handle_api(): |
|
response = api() |
|
return response |
|
|
|
|
|
@app.route("/save_db", methods=['GET']) |
|
def handle_save_db(): |
|
response = save_db() |
|
return response |
|
|
|
|
|
@app.route('/set_res') |
|
def set_res(): |
|
globs.eep_set = 0 |
|
return jsonify(value_set="reset") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 7860))) |