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, onA TEXT, onB TEXT, onC 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.onA = 0 globs.onB = 0 globs.onC = 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 # Создаем экземпляр Flask-приложения 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, onA, onB, onC ) 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['onA'], data['onB'], data['onC'] )) 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'), 'onA': request.args.get('onA'), 'onB': request.args.get('onB'), 'onC': request.args.get('onC') } # Проверяем, что все необходимые параметры переданы required_params = ['dey', 'wek', 'v_hid', 'v_min', 'ph', 'ec', 'tS', 'tA', 'hDm', 'sVen', 'onA', 'onB', 'onC'] 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] # Преобразуем данные в формат JSON data = [] for row in rows: data.append(dict(zip(column_names, row))) conn.close() # Возвращаем данные в формате JSON 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: # Получаем параметры из URL (если они есть) start_date = request.args.get('start_date') end_date = request.args.get('end_date') # Если параметры есть, проверяем их корректность if start_date and end_date: try: # Преобразуем даты в формат datetime 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 '''

Неправильная дата выбрана

Дата начала должна быть раньше даты окончания.

''' except ValueError: return '''

Неправильная дата выбрана

Формат даты должен быть YYYY-MM-DDTHH:MM.

''' # Подключаемся к базе данных 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 '''

В базе данных отсутствуют значения

Таблица system_data не существует. Обновите базу данных.

''' # Выполняем запрос для получения данных в заданном диапазоне 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 '''

Данные отсутствуют в базе данных

Для выбранного диапазона дат данные не найдены.

''' # Разделяем данные на дату и время, а также добавляем значения из столбцов dey и wek dates = [f"{row[0]} d: {row[2]} w: {row[3]}" for row in rows] # Дата и время + dey + wek ph_values = [float(row[1]) for row in rows] # Значения pH # Создаем график 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) # Поворачиваем подписи оси X вертикально plt.grid(True) plt.gcf().subplots_adjust(bottom=0.4) # Увеличиваем пространство снизу для надписей # Сохраняем график в буфер buffer = io.BytesIO() plt.savefig(buffer, format='png') buffer.seek(0) # Кодируем график в base64 plot_data = base64.b64encode(buffer.getvalue()).decode('utf-8') # Возвращаем график в формате HTML с кнопками "Новые данные" и "Обновить данные" return f'''

График значений pH



График pH ''' # Если параметров нет, отображаем форму для ввода даты и времени return '''

Выберите диапазон даты и времени для графика pH





''' except Exception as e: return jsonify({'status': 'error', 'message': str(e)}), 500 @app.route('/plot_ph_week', methods=['GET']) def plot_ph_week(): try: week_number = request.args.get('week', default=1, type=int) if week_number < 1: week_number = 1 elif week_number > 30: week_number = 30 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 '''

Ошибка!

Таблица system_data не существует.

''' cursor.execute(''' SELECT date_time, ph, ec, dey, onA, onB, onC FROM system_data WHERE wek = ? ORDER BY date_time ''', (week_number,)) rows = cursor.fetchall() conn.close() if not rows: return f'''

Данных нет

За {week_number}-ю неделю данных нет.

''' dates = [f"{row[0]} (d: {row[3]})" for row in rows] ph_values = [float(row[1]) for row in rows] ec_values = [float(row[2]) for row in rows] onA_values = [float(row[4]) for row in rows] onB_values = [float(row[5]) for row in rows] onC_values = [float(row[6]) for row in rows] plt.figure(figsize=(15, 18)) # Увеличил высоту для трех графиков # График pH plt.subplot(3, 1, 1) plt.plot(dates, ph_values, linestyle='-', color='b') plt.title(f'График pH за {week_number}-ю неделю', fontsize=14) plt.xlabel('Дата и день недели', fontsize=12) plt.ylabel('Значение pH', fontsize=12) plt.xticks(rotation=90, fontsize=6) plt.grid(True) # График EC plt.subplot(3, 1, 2) plt.plot(dates, ec_values, linestyle='-', color='g') plt.title(f'График EC за {week_number}-ю неделю', fontsize=14) plt.xlabel('Дата и день недели', fontsize=12) plt.ylabel('Значение EC', fontsize=12) plt.xticks(rotation=90, fontsize=6) plt.grid(True) # График насосов plt.subplot(3, 1, 3) plt.plot(dates, onA_values, linestyle='-', color='green', label='Насос A') plt.plot(dates, onB_values, linestyle='-', color='brown', label='Насос B') plt.plot(dates, onC_values, linestyle='-', color='orange', label='Насос C') plt.title(f'График работы насосов за {week_number}-ю неделю', fontsize=14) plt.xlabel('Дата и день недели', fontsize=12) plt.ylabel('Состояние насосов', fontsize=12) plt.xticks(rotation=90, fontsize=6) plt.legend() plt.grid(True) # Увеличиваем расстояние между графиками plt.subplots_adjust(hspace=1.2, bottom=0.1, top=0.95) buffer = io.BytesIO() plt.savefig(buffer, format='png') buffer.seek(0) plot_data = base64.b64encode(buffer.getvalue()).decode('utf-8') return f'''

Графики за {week_number}-ю неделю



Графики pH, EC и насосов ''' 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('/calculate', methods=['GET']) def calculate(): return render_template('calculate.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.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)))