531 lines
22 KiB
Python
531 lines
22 KiB
Python
![]() |
from flask import Blueprint, jsonify, request, current_app, g
|
|||
|
import sqlite3
|
|||
|
import datetime
|
|||
|
from dateutil.relativedelta import relativedelta
|
|||
|
import logging
|
|||
|
import random
|
|||
|
|
|||
|
# 配置日志
|
|||
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|||
|
logger = logging.getLogger(__name__)
|
|||
|
|
|||
|
bp = Blueprint('ph_data', __name__, url_prefix='/ph_data')
|
|||
|
|
|||
|
# 数据缓存字典,格式: {time_range: (seed, cached_data)}
|
|||
|
ph_data_cache = {}
|
|||
|
|
|||
|
|
|||
|
def get_db():
|
|||
|
"""获取数据库连接"""
|
|||
|
if 'db' not in g:
|
|||
|
try:
|
|||
|
g.db = sqlite3.connect(
|
|||
|
current_app.config.get('DATABASE', 'agriculture.db'),
|
|||
|
check_same_thread=False,
|
|||
|
detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES
|
|||
|
)
|
|||
|
g.db.row_factory = sqlite3.Row
|
|||
|
logger.info("数据库连接成功")
|
|||
|
except Exception as e:
|
|||
|
logger.error(f"数据库连接失败: {str(e)}")
|
|||
|
raise
|
|||
|
return g.db
|
|||
|
|
|||
|
|
|||
|
def close_db(e=None):
|
|||
|
"""关闭数据库连接"""
|
|||
|
db = g.pop('db', None)
|
|||
|
if db is not None:
|
|||
|
db.close()
|
|||
|
logger.info("数据库连接已关闭")
|
|||
|
|
|||
|
|
|||
|
@bp.route('/get_time_ranges', methods=['GET'])
|
|||
|
def get_time_ranges():
|
|||
|
"""获取时间范围选项"""
|
|||
|
try:
|
|||
|
time_ranges = [
|
|||
|
{'value': 'today', 'label': '今日'},
|
|||
|
{'value': 'last_three_days', 'label': '前三天'},
|
|||
|
{'value': 'next_two_days', 'label': '后两天'},
|
|||
|
]
|
|||
|
logger.info("成功返回时间范围选项")
|
|||
|
return jsonify({'time_ranges': time_ranges})
|
|||
|
except Exception as e:
|
|||
|
logger.error(f"获取时间范围失败: {str(e)}")
|
|||
|
return jsonify({'error': '获取时间范围失败'}), 500
|
|||
|
|
|||
|
|
|||
|
def increase_ph_fluctuation(data_list, time_range, amplitude=1.5):
|
|||
|
"""
|
|||
|
增加PH值的波动幅度,使用固定随机种子确保相同时间范围生成相同波动数据
|
|||
|
:param data_list: 包含PH值的数据列表
|
|||
|
:param time_range: 时间范围参数
|
|||
|
:param amplitude: 波动幅度(默认±1.5)
|
|||
|
:return: 修改后的列表
|
|||
|
"""
|
|||
|
# 检查缓存
|
|||
|
if time_range in ph_data_cache:
|
|||
|
logger.info(f"使用缓存的波动数据 for {time_range}")
|
|||
|
return ph_data_cache[time_range]
|
|||
|
|
|||
|
# 为特定时间范围设置固定随机种子
|
|||
|
seed = hash(time_range)
|
|||
|
random.seed(seed)
|
|||
|
logger.info(f"为时间范围 {time_range} 设置随机种子: {seed}")
|
|||
|
|
|||
|
# 应用波动
|
|||
|
modified_data = []
|
|||
|
for item in data_list:
|
|||
|
original_ph = item.get('ph') or item.get('avg_ph')
|
|||
|
if original_ph is not None:
|
|||
|
# 随机波动(可正可负)
|
|||
|
fluctuation = random.uniform(-amplitude, amplitude)
|
|||
|
new_ph = original_ph + fluctuation
|
|||
|
# 确保PH值在合理范围(0-14)
|
|||
|
new_ph = max(0, min(14, new_ph))
|
|||
|
# 更新数据
|
|||
|
modified_item = item.copy()
|
|||
|
if 'ph' in modified_item:
|
|||
|
modified_item['ph'] = round(new_ph, 2)
|
|||
|
else:
|
|||
|
modified_item['avg_ph'] = round(new_ph, 2)
|
|||
|
modified_data.append(modified_item)
|
|||
|
|
|||
|
# 缓存波动后的数据
|
|||
|
ph_data_cache[time_range] = modified_data
|
|||
|
return modified_data
|
|||
|
|
|||
|
|
|||
|
@bp.route('/get_ph_data', methods=['GET'])
|
|||
|
def get_ph_data():
|
|||
|
"""获取指定时间范围的PH值数据(合并所有设备)"""
|
|||
|
time_range = request.args.get('time_range', 'today')
|
|||
|
sample_method = request.args.get('sample_method', 'fixed') # 采样方式:fixed(固定点)或hourly(每小时)
|
|||
|
logger.info(f"请求PH数据,时间范围: {time_range},采样方式: {sample_method}")
|
|||
|
|
|||
|
if time_range not in ['today', 'last_three_days', 'next_two_days', 'all']:
|
|||
|
logger.warning(f"无效的时间范围: {time_range}")
|
|||
|
return jsonify({'error': '无效的时间范围'}), 400
|
|||
|
|
|||
|
try:
|
|||
|
db = get_db()
|
|||
|
# 硬编码今日为2025-05-27
|
|||
|
today = datetime.datetime(2025, 5, 27)
|
|||
|
today_str = today.strftime('%Y-%m-%d')
|
|||
|
|
|||
|
result = []
|
|||
|
|
|||
|
if time_range == 'today':
|
|||
|
# 今日数据查询逻辑
|
|||
|
start_date = today_str + ' 00:00:00'
|
|||
|
end_date = today_str + ' 23:59:59'
|
|||
|
|
|||
|
if sample_method == 'hourly':
|
|||
|
# 每小时采样
|
|||
|
for hour in range(0, 24):
|
|||
|
sample_time = f"{today_str} {hour:02d}:00:00"
|
|||
|
start_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
- relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
end_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
+ relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
|
|||
|
cursor = db.execute(
|
|||
|
'''SELECT AVG(ph) as avg_ph
|
|||
|
FROM temperature_data
|
|||
|
WHERE (timestamp BETWEEN ? AND ?)
|
|||
|
OR (DATE(timestamp) = DATE(?))''',
|
|||
|
(start_time, end_time, sample_time)
|
|||
|
)
|
|||
|
row = cursor.fetchone()
|
|||
|
avg_ph = float(row['avg_ph']) if row and row['avg_ph'] is not None else 0
|
|||
|
|
|||
|
result.append({
|
|||
|
'timestamp': sample_time,
|
|||
|
'ph': round(avg_ph, 2)
|
|||
|
})
|
|||
|
else:
|
|||
|
# 固定点采样
|
|||
|
cursor = db.execute(
|
|||
|
'''SELECT timestamp, AVG(ph) as avg_ph
|
|||
|
FROM temperature_data
|
|||
|
WHERE (timestamp BETWEEN ? AND ?)
|
|||
|
OR (DATE(timestamp) = DATE(?))
|
|||
|
GROUP BY timestamp
|
|||
|
ORDER BY timestamp''',
|
|||
|
(start_date, end_date, today_str)
|
|||
|
)
|
|||
|
data = cursor.fetchall()
|
|||
|
result = [{'timestamp': row['timestamp'], 'ph': float(row['avg_ph'])} for row in data]
|
|||
|
|
|||
|
logger.info(f"查询到今日PH数据记录: {len(result)} 条")
|
|||
|
|
|||
|
elif time_range == 'last_three_days':
|
|||
|
# 前三天数据查询
|
|||
|
if sample_method == 'hourly':
|
|||
|
# 每小时采样
|
|||
|
for i in range(3, 0, -1):
|
|||
|
date = today - relativedelta(days=i)
|
|||
|
date_str = date.strftime('%Y-%m-%d')
|
|||
|
for hour in range(0, 24):
|
|||
|
sample_time = f"{date_str} {hour:02d}:00:00"
|
|||
|
start_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
- relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
end_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
+ relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
|
|||
|
cursor = db.execute(
|
|||
|
'''SELECT AVG(ph) as avg_ph
|
|||
|
FROM temperature_data
|
|||
|
WHERE (timestamp BETWEEN ? AND ?)
|
|||
|
OR (DATE(timestamp) = DATE(?))''',
|
|||
|
(start_time, end_time, sample_time)
|
|||
|
)
|
|||
|
row = cursor.fetchone()
|
|||
|
avg_ph = float(row['avg_ph']) if row and row['avg_ph'] is not None else 0
|
|||
|
|
|||
|
result.append({
|
|||
|
'timestamp': sample_time,
|
|||
|
'ph': round(avg_ph, 2)
|
|||
|
})
|
|||
|
else:
|
|||
|
# 固定点采样(每天6个点)
|
|||
|
sample_hours = [4, 8, 12, 16, 20, 23]
|
|||
|
for i in range(3, 0, -1):
|
|||
|
date = today - relativedelta(days=i)
|
|||
|
date_str = date.strftime('%Y-%m-%d')
|
|||
|
for hour in sample_hours:
|
|||
|
if hour == 23:
|
|||
|
sample_time = f"{date_str} {hour:02d}:00:00"
|
|||
|
else:
|
|||
|
sample_time = f"{date_str} {hour:02d}:00:00"
|
|||
|
|
|||
|
start_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
- relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
end_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
+ relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
|
|||
|
cursor = db.execute(
|
|||
|
'''SELECT AVG(ph) as avg_ph
|
|||
|
FROM temperature_data
|
|||
|
WHERE (timestamp BETWEEN ? AND ?)
|
|||
|
OR (DATE(timestamp) = DATE(?))''',
|
|||
|
(start_time, end_time, sample_time)
|
|||
|
)
|
|||
|
row = cursor.fetchone()
|
|||
|
avg_ph = float(row['avg_ph']) if row and row['avg_ph'] is not None else 0
|
|||
|
|
|||
|
result.append({
|
|||
|
'timestamp': sample_time,
|
|||
|
'ph': round(avg_ph, 2)
|
|||
|
})
|
|||
|
|
|||
|
logger.info(f"查询到前三天PH数据记录: {len(result)} 条")
|
|||
|
|
|||
|
elif time_range == 'next_two_days':
|
|||
|
# 后两天数据查询
|
|||
|
if sample_method == 'hourly':
|
|||
|
for i in range(1, 3):
|
|||
|
date = today + relativedelta(days=i)
|
|||
|
date_str = date.strftime('%Y-%m-%d')
|
|||
|
for hour in range(0, 24):
|
|||
|
sample_time = f"{date_str} {hour:02d}:00:00"
|
|||
|
start_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
- relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
end_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
+ relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
|
|||
|
cursor = db.execute(
|
|||
|
'''SELECT AVG(ph) as avg_ph
|
|||
|
FROM temperature_data
|
|||
|
WHERE (timestamp BETWEEN ? AND ?)
|
|||
|
OR (DATE(timestamp) = DATE(?))''',
|
|||
|
(start_time, end_time, sample_time)
|
|||
|
)
|
|||
|
row = cursor.fetchone()
|
|||
|
avg_ph = float(row['avg_ph']) if row and row['avg_ph'] is not None else 0
|
|||
|
|
|||
|
result.append({
|
|||
|
'timestamp': sample_time,
|
|||
|
'ph': round(avg_ph, 2)
|
|||
|
})
|
|||
|
else:
|
|||
|
sample_hours = [8, 12, 16, 20]
|
|||
|
for i in range(1, 3):
|
|||
|
date = today + relativedelta(days=i)
|
|||
|
date_str = date.strftime('%Y-%m-%d')
|
|||
|
for hour in sample_hours:
|
|||
|
sample_time = f"{date_str} {hour:02d}:00:00"
|
|||
|
start_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
- relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
end_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
+ relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
|
|||
|
cursor = db.execute(
|
|||
|
'''SELECT AVG(ph) as avg_ph
|
|||
|
FROM temperature_data
|
|||
|
WHERE (timestamp BETWEEN ? AND ?)
|
|||
|
OR (DATE(timestamp) = DATE(?))''',
|
|||
|
(start_time, end_time, sample_time)
|
|||
|
)
|
|||
|
row = cursor.fetchone()
|
|||
|
avg_ph = float(row['avg_ph']) if row and row['avg_ph'] is not None else 0
|
|||
|
|
|||
|
result.append({
|
|||
|
'timestamp': sample_time,
|
|||
|
'ph': round(avg_ph, 2)
|
|||
|
})
|
|||
|
|
|||
|
logger.info(f"查询到后两天PH数据记录: {len(result)} 条")
|
|||
|
|
|||
|
elif time_range == 'all':
|
|||
|
# 查询所有PH数据
|
|||
|
cursor = db.execute(
|
|||
|
'''SELECT timestamp, AVG(ph) as avg_ph
|
|||
|
FROM temperature_data
|
|||
|
WHERE ph IS NOT NULL
|
|||
|
GROUP BY timestamp
|
|||
|
ORDER BY timestamp'''
|
|||
|
)
|
|||
|
data = cursor.fetchall()
|
|||
|
result = [{'timestamp': row['timestamp'], 'ph': float(row['avg_ph'])} for row in data]
|
|||
|
logger.info(f"查询到所有PH数据记录: {len(result)} 条")
|
|||
|
|
|||
|
# 关键修改:使用带随机种子的波动函数,并缓存结果
|
|||
|
result = increase_ph_fluctuation(result, time_range, amplitude=2.0)
|
|||
|
|
|||
|
return jsonify({
|
|||
|
'time_range': time_range,
|
|||
|
'sample_method': sample_method,
|
|||
|
'data': result
|
|||
|
})
|
|||
|
|
|||
|
except sqlite3.Error as e:
|
|||
|
logger.error(f"数据库查询错误: {str(e)}")
|
|||
|
return jsonify({'error': '数据库查询错误'}), 500
|
|||
|
except Exception as e:
|
|||
|
logger.error(f"获取PH数据异常: {str(e)}")
|
|||
|
return jsonify({'error': '服务器内部错误'}), 500
|
|||
|
finally:
|
|||
|
close_db()
|
|||
|
|
|||
|
|
|||
|
@bp.route('/get_ph_data_by_date_range', methods=['GET'])
|
|||
|
def get_ph_data_by_date_range():
|
|||
|
"""获取指定日期范围内的PH值数据(合并所有设备)"""
|
|||
|
start_date_str = request.args.get('start_date')
|
|||
|
end_date_str = request.args.get('end_date')
|
|||
|
sample_method = request.args.get('sample_method', 'daily') # 采样方式:daily(每日)或hourly(每小时)
|
|||
|
|
|||
|
# 验证日期格式
|
|||
|
try:
|
|||
|
start_date = datetime.datetime.strptime(start_date_str, '%Y-%m-%d')
|
|||
|
end_date = datetime.datetime.strptime(end_date_str, '%Y-%m-%d')
|
|||
|
except ValueError:
|
|||
|
logger.warning(f"无效的日期格式,需要YYYY-MM-DD格式,实际传入: {start_date_str}, {end_date_str}")
|
|||
|
return jsonify({'error': '无效的日期格式,需要YYYY-MM-DD格式'}), 400
|
|||
|
|
|||
|
# 验证日期范围
|
|||
|
if start_date > end_date:
|
|||
|
logger.warning(f"开始日期不能大于结束日期: {start_date_str} > {end_date_str}")
|
|||
|
return jsonify({'error': '开始日期不能大于结束日期'}), 400
|
|||
|
|
|||
|
logger.info(f"请求PH数据,日期范围: {start_date_str} 至 {end_date_str},采样方式: {sample_method}")
|
|||
|
|
|||
|
try:
|
|||
|
db = get_db()
|
|||
|
result = []
|
|||
|
|
|||
|
if sample_method == 'hourly':
|
|||
|
# 每小时采样
|
|||
|
current_date = start_date
|
|||
|
while current_date <= end_date:
|
|||
|
date_str = current_date.strftime('%Y-%m-%d')
|
|||
|
for hour in range(0, 24):
|
|||
|
sample_time = f"{date_str} {hour:02d}:00:00"
|
|||
|
start_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
- relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
end_time = (datetime.datetime.strptime(sample_time, '%Y-%m-%d %H:%M:%S')
|
|||
|
+ relativedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S')
|
|||
|
|
|||
|
cursor = db.execute(
|
|||
|
'''SELECT AVG(ph) as avg_ph
|
|||
|
FROM temperature_data
|
|||
|
WHERE (timestamp BETWEEN ? AND ?)
|
|||
|
OR (DATE(timestamp) = DATE(?))''',
|
|||
|
(start_time, end_time, sample_time)
|
|||
|
)
|
|||
|
row = cursor.fetchone()
|
|||
|
avg_ph = float(row['avg_ph']) if row and row['avg_ph'] is not None else 0
|
|||
|
|
|||
|
result.append({
|
|||
|
'timestamp': sample_time,
|
|||
|
'ph': round(avg_ph, 2)
|
|||
|
})
|
|||
|
current_date += relativedelta(days=1)
|
|||
|
else:
|
|||
|
# 每日采样
|
|||
|
current_date = start_date
|
|||
|
while current_date <= end_date:
|
|||
|
date_str = current_date.strftime('%Y-%m-%d')
|
|||
|
cursor = db.execute(
|
|||
|
'''SELECT AVG(ph) as avg_ph
|
|||
|
FROM temperature_data
|
|||
|
WHERE DATE(timestamp) = ?''',
|
|||
|
(date_str,)
|
|||
|
)
|
|||
|
row = cursor.fetchone()
|
|||
|
avg_ph = float(row['avg_ph']) if row and row['avg_ph'] is not None else 0
|
|||
|
|
|||
|
result.append({
|
|||
|
'date': date_str,
|
|||
|
'avg_ph': round(avg_ph, 2)
|
|||
|
})
|
|||
|
current_date += relativedelta(days=1)
|
|||
|
|
|||
|
logger.info(f"查询到{start_date_str}至{end_date_str}的PH数据记录: {len(result)} 条")
|
|||
|
|
|||
|
# 增加PH值的波动幅度,使用日期范围字符串作为种子
|
|||
|
range_key = f"{start_date_str}_{end_date_str}"
|
|||
|
result = increase_ph_fluctuation(result, range_key, amplitude=2.0)
|
|||
|
|
|||
|
return jsonify({
|
|||
|
'start_date': start_date_str,
|
|||
|
'end_date': end_date_str,
|
|||
|
'sample_method': sample_method,
|
|||
|
'data': result
|
|||
|
})
|
|||
|
|
|||
|
except sqlite3.Error as e:
|
|||
|
logger.error(f"数据库查询错误: {str(e)}")
|
|||
|
return jsonify({'error': '数据库查询错误'}), 500
|
|||
|
except Exception as e:
|
|||
|
logger.error(f"获取PH数据异常: {str(e)}")
|
|||
|
return jsonify({'error': '服务器内部错误'}), 500
|
|||
|
finally:
|
|||
|
close_db()
|
|||
|
|
|||
|
|
|||
|
@bp.route('/get_ph_today', methods=['GET'])
|
|||
|
def get_ph_today():
|
|||
|
"""获取2025年5月27日设备1的所有PH值数据"""
|
|||
|
logger.info("请求获取2025年5月27日设备1的PH数据")
|
|||
|
try:
|
|||
|
db = get_db()
|
|||
|
target_date = datetime.datetime(2025, 5, 27)
|
|||
|
start = target_date.strftime('%Y-%m-%d 00:00:00')
|
|||
|
end = target_date.strftime('%Y-%m-%d 23:59:59')
|
|||
|
|
|||
|
logger.info(f"查询范围: {start} ~ {end},设备ID: 1")
|
|||
|
cursor = db.execute(
|
|||
|
'''SELECT timestamp, ph
|
|||
|
FROM temperature_data
|
|||
|
WHERE timestamp BETWEEN ? AND ?
|
|||
|
AND ph IS NOT NULL
|
|||
|
AND device_id = 1 -- 只查询设备1的数据
|
|||
|
ORDER BY timestamp''',
|
|||
|
(start, end)
|
|||
|
)
|
|||
|
data = cursor.fetchall()
|
|||
|
|
|||
|
if not data:
|
|||
|
logger.warning("2025-05-27设备1无PH数据,查询最近10条调试")
|
|||
|
debug_cursor = db.execute('''
|
|||
|
SELECT timestamp, ph, device_id
|
|||
|
FROM temperature_data
|
|||
|
ORDER BY timestamp DESC
|
|||
|
LIMIT 10
|
|||
|
''')
|
|||
|
recent = debug_cursor.fetchall()
|
|||
|
logger.info("数据库最近10条记录:")
|
|||
|
for record in recent:
|
|||
|
logger.info(f" timestamp: {record['timestamp']}, ph: {record['ph']}, device_id: {record['device_id']}")
|
|||
|
return jsonify({
|
|||
|
'date': '2025-05-27',
|
|||
|
'device_id': 1,
|
|||
|
'message': '未找到设备1的PH数据',
|
|||
|
'data': []
|
|||
|
})
|
|||
|
|
|||
|
result = []
|
|||
|
for i, row in enumerate(data):
|
|||
|
try:
|
|||
|
# 提取原始数据
|
|||
|
raw_ts = row['timestamp']
|
|||
|
raw_ph = row['ph']
|
|||
|
|
|||
|
# 验证时间格式
|
|||
|
if isinstance(raw_ts, datetime.datetime):
|
|||
|
dt = raw_ts
|
|||
|
else:
|
|||
|
dt = datetime.datetime.strptime(raw_ts, '%Y-%m-%d %H:%M:%S')
|
|||
|
|
|||
|
# 验证PH值
|
|||
|
if raw_ph is None:
|
|||
|
continue # 跳过空值
|
|||
|
|
|||
|
if isinstance(raw_ph, (float, int)):
|
|||
|
ph_value = raw_ph
|
|||
|
elif isinstance(raw_ph, str):
|
|||
|
ph_str = raw_ph.strip()
|
|||
|
if 'pH' in ph_str:
|
|||
|
ph_str = ph_str.replace('pH', '').strip()
|
|||
|
ph_value = float(ph_str)
|
|||
|
else:
|
|||
|
ph_value = float(raw_ph)
|
|||
|
|
|||
|
result.append({
|
|||
|
'timestamp': raw_ts.strftime('%Y-%m-%d %H:%M:%S') if isinstance(raw_ts,
|
|||
|
datetime.datetime) else raw_ts,
|
|||
|
'ph': round(ph_value, 2),
|
|||
|
'formatted_time': dt.strftime('%H:%M')
|
|||
|
})
|
|||
|
except ValueError as ve:
|
|||
|
logger.error(f"第 {i + 1} 条记录格式错误: {str(ve)}")
|
|||
|
logger.error(f" 原始数据: timestamp={raw_ts}, ph={raw_ph}")
|
|||
|
except TypeError as te:
|
|||
|
logger.error(f"第 {i + 1} 条记录类型错误: {str(te)}")
|
|||
|
logger.error(f" 原始数据: timestamp={raw_ts}, ph={raw_ph}")
|
|||
|
except Exception as e:
|
|||
|
logger.error(f"处理第 {i + 1} 条记录时未知错误: {str(e)}")
|
|||
|
|
|||
|
if not result:
|
|||
|
logger.warning("设备1的所有记录处理后无有效数据")
|
|||
|
return jsonify({
|
|||
|
'date': '2025-05-27',
|
|||
|
'device_id': 1,
|
|||
|
'message': '数据格式错误,无有效PH值',
|
|||
|
'data': []
|
|||
|
})
|
|||
|
|
|||
|
logger.info(f"成功处理设备1的 {len(result)} 条有效数据")
|
|||
|
return jsonify({
|
|||
|
'date': '2025-05-27',
|
|||
|
'device_id': 1,
|
|||
|
'total_records': len(result),
|
|||
|
'data': result
|
|||
|
})
|
|||
|
|
|||
|
except sqlite3.OperationalError as oe:
|
|||
|
logger.error(f"数据库操作错误: {str(oe)}", exc_info=True)
|
|||
|
return jsonify({
|
|||
|
'date': '2025-05-27',
|
|||
|
'device_id': 1,
|
|||
|
'error': f'数据库操作错误: {str(oe)}'
|
|||
|
}), 500
|
|||
|
except sqlite3.Error as se:
|
|||
|
logger.error(f"数据库错误: {str(se)}", exc_info=True)
|
|||
|
return jsonify({
|
|||
|
'date': '2025-05-27',
|
|||
|
'device_id': 1,
|
|||
|
'error': f'数据库错误: {str(se)}'
|
|||
|
}), 500
|
|||
|
except Exception as e:
|
|||
|
logger.error(f"未知异常: {str(e)}", exc_info=True)
|
|||
|
return jsonify({
|
|||
|
'date': '2025-05-27',
|
|||
|
'device_id': 1,
|
|||
|
'error': f'未知错误: {str(e)}'
|
|||
|
}), 500
|
|||
|
finally:
|
|||
|
close_db()
|