DmitrMakeev's picture
Update app.py
67fbbc8 verified
raw
history blame
24.9 kB
import flask
from flask import request, jsonify
from flask import Flask, request, jsonify
from aiogram import Bot, Dispatcher, types
from aiohttp import web
import asyncio
import os
import sqlite3
from datetime import datetime
import pytz # Импортируем библиотеку для работы с часовыми поясами
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,
nPh TEXT,
nEC TEXT,
nTa TEXT,
nLon TEXT,
nLoff TEXT
)
''')
# **Новая таблица для пользователей бота**
cursor.execute('''
CREATE TABLE IF NOT EXISTS bot_users (
id INTEGER PRIMARY KEY AUTOINCREMENT, -- Уникальный ID
chat_id INTEGER UNIQUE, -- Telegram ID пользователя
created_at TEXT -- Время добавления (ISO формат)
)
''')
conn.commit()
conn.close()
# Глобальные переменные
api_key_sys = os.getenv('api_key') # Берём значение API-ключа из .env
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
# Токен Telegram бота
@app.route('/bt_test', methods=['GET', 'POST'])
def bt_test():
if request.method == 'POST':
if 'product_name' in request.form:
product_name = request.form['product_name']
send_to_telegram(product_name)
return redirect(url_for('bt_test'))
else:
return 'No product name provided', 400 # Возвращаем ошибку если нет имени продукта
return render_template('bt_test.html')
def send_to_telegram(product_name):
bot_token = '7766407698:AAGZHEbUuiOri4_YzZ7hDPSD6U8MGMXXSnA'
chat_id = '1343658673'
message = f'Новый продукт добавлен: {product_name}'
try:
response = requests.get(f'https://api.telegram.org/bot{bot_token}/sendMessage', params={
'chat_id': chat_id,
'text': message
})
response.raise_for_status() # Проверяем успешность запроса
except requests.exceptions.RequestException as e:
print(f'Error sending message to Telegram: {e}')
# Функция сохранения в базу пользователей TG
def save_user(chat_id, db_name="your_database.db"):
conn = sqlite3.connect(db_name)
cursor = conn.cursor()
created_at = datetime.now().isoformat() # Форматируем дату
try:
cursor.execute("INSERT INTO bot_users (chat_id, created_at) VALUES (?, ?)", (chat_id, created_at))
conn.commit()
except sqlite3.IntegrityError:
print(f"Пользователь {chat_id} уже есть в базе.")
conn.close()
# Функция сохранения в базу данных системы автоматизации гидропоники
def save_data_to_db(db_name, data):
try:
conn = sqlite3.connect(db_name)
cursor = conn.cursor()
# ✅ Устанавливаем московское время (UTC+3)
moscow_tz = pytz.timezone("Europe/Moscow")
current_time = datetime.now(moscow_tz).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, nPh, nEC, nTa, nLon, nLoff
) 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'], data['nPh'], data['nEC'], data['nTa'], data['nLon'], data['nLoff']
))
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'),
'nPh': request.args.get('nPh'),
'nEC': request.args.get('nEC'),
'nTa': request.args.get('nTa'),
'nLon': request.args.get('nLon'),
'nLoff': request.args.get('nLoff')
}
# Проверяем, что все необходимые параметры переданы
required_params = ['dey', 'wek', 'v_hid', 'v_min', 'ph', 'ec', 'tS', 'tA', 'hDm', 'sVen', 'onA', 'onB', 'onC', 'nPh', 'nEC', 'nTa', 'nLon', 'nLoff']
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': 'Save OK'})
# Проверка входа на страницы
@app.route('/page_key', methods=['GET'])
def check_api_key():
api_sys_param = request.args.get('api_sys') # Получаем параметр из запроса
if api_sys_param == api_key_sys:
return jsonify({"status": "ok"}), 200 # ✅ Совпадает — отправляем "ok"
else:
return jsonify({"status": "error", "message": "Invalid API key"}), 403 # ❌ Ошибка 403
# Тестовый запрос с установки
@app.route('/test_server', methods=['GET'])
def test_server():
api_key_param = request.args.get('api_sys') # Получаем параметр из запроса
err_ser = 1 if api_key_param == api_key_sys else 0 # Проверяем совпадение ключей
return jsonify(err_ser=err_ser)
@app.route('/test_server_str', methods=['GET'])
def test_server_str():
api_key_param = request.args.get('api_sys')
err_ser = "1" if api_key_param == api_key_sys else "0"
return err_ser # Возвращаем строку "1" или "0"
# Маршрут для вывода всех данных из таблицы
@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('/delite_db', methods=['GET'])
def delete_db():
try:
conn = sqlite3.connect("system_data.db") # Используем вашу БД
cursor = conn.cursor()
# ✅ Удаляем все записи из таблицы
cursor.execute("DELETE FROM system_data")
# ✅ Сбрасываем автоинкрементный счётчик ID (для SQLite)
cursor.execute("DELETE FROM sqlite_sequence WHERE name='system_data'")
conn.commit()
conn.close()
return jsonify({'status': 'ok', 'message': 'База данных успешно очищена'})
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 '''
<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>
'''
# Разделяем данные на дату и время, а также добавляем значения из столбцов 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'''
<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('/plot_week', methods=['GET'])
def plot_week():
try:
# Получаем номер недели из параметров запроса
week_number = request.args.get('week', default=1, type=int)
week_number = max(1, min(30, week_number)) # Ограничиваем диапазон 1-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:
conn.close()
return render_template('plot_week.html', data=None, week_number=week_number, table_exists=False)
# Запрашиваем данные за выбранную неделю
cursor.execute('''
SELECT date_time, dey, ph, ec, tS, tA, hDm, sVen, onA, onB, onC, v_hid, v_min
FROM system_data
WHERE wek = ?
ORDER BY date_time
''', (str(week_number),)) # Приводим week_number к строке, так как wek имеет тип TEXT
rows = cursor.fetchall()
conn.close()
# Если данных нет
if not rows:
return render_template('plot_week.html', data=None, week_number=week_number, table_exists=True)
# Формируем данные для JSON
data = {
'week': week_number,
'dates': [row[0] for row in rows],
'days_of_week': [int(row[1]) if row[1] else 0 for row in rows], # Преобразуем dey в int
'ph': [float(row[2]) if row[2] else 0.0 for row in rows], # pH
'ec': [float(row[3]) if row[3] else 0.0 for row in rows], # EC
'tS': [float(row[4]) if row[4] else 0.0 for row in rows], # Температура раствора
'tA': [float(row[5]) if row[5] else 0.0 for row in rows], # Температура воздуха
'hDm': [float(row[6]) if row[6] else 0.0 for row in rows], # Влажность воздуха
'sVen': [float(row[7]) if row[7] else 0.0 for row in rows], # Обороты вентилятора
'onA': [float(row[8]) if row[8] else 0.0 for row in rows], # Насос A
'onB': [float(row[9]) if row[9] else 0.0 for row in rows], # Насос B
'onC': [float(row[10]) if row[10] else 0.0 for row in rows], # Насос C
'sus': [f"{row[11]}:{row[12]}" if row[11] and row[12] else "0:0" for row in rows] # Объединяем v_hid и v_min
}
# Отправляем данные в HTML-шаблон
return render_template('plot_week.html', data=data, week_number=week_number, table_exists=True)
except Exception as e:
# Логируем ошибку в консоль для отладки
print(f"Ошибка: {str(e)}")
return render_template('plot_week.html', data=None, week_number=week_number, table_exists=True, message=f"Ошибка: {str(e)}")
@app.route("/")
def index():
return flask.render_template('index.html')
@app.route('/online', methods=['GET'])
def online():
return render_template('online.html')
@app.route('/table', methods=['GET'])
def table():
return render_template('table.html')
@app.route('/online_api', methods=['GET'])
def online_api():
# Устанавливаем московское время (UTC+3)
moscow_tz = pytz.timezone("Europe/Moscow")
current_time = datetime.now(moscow_tz)
# Форматируем дату и время отдельно
date = current_time.strftime('%Y-%m-%d') # Например, "2025-03-23"
time = current_time.strftime('%H:%M:%S') # Например, "14:35:42"
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,
ec_A_eep=globs.ec_A_eep,
ec_B_eep=globs.ec_B_eep,
ec_C_eep=globs.ec_C_eep,
date=date, # Добавляем дату
time=time # Добавляем время
)
@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)))