|
|
@@ -1,11 +1,26 @@
|
|
|
#!/usr/bin/env python
|
|
|
# -*- coding: utf-8 -*-
|
|
|
"""
|
|
|
-查询td_d_log_result表,筛选符合条件的device_id和channel_no组合
|
|
|
-筛选条件:
|
|
|
+查询td_d_log_result表和td_d_log_file表,筛选符合条件的device_id和channel_no组合
|
|
|
+
|
|
|
+筛选条件(两种类型):
|
|
|
- task_id = 2
|
|
|
-- 对于每个device_id和channel_no的组合,取最新的10条记录(按channel_no的generate_time)
|
|
|
-- 如果这10个value值中有超过3个值大于20,则记录该(device_id, channel_no)组合
|
|
|
+
|
|
|
+第一种类型(value>30):
|
|
|
+- 对于每个device_id和channel_no的组合,取最新的10条记录(按generate_time)
|
|
|
+- 计算这10个value值的平均值
|
|
|
+- 如果平均值大于30,则记录该(device_id, channel_no)组合
|
|
|
+
|
|
|
+第二种类型(abs>2):
|
|
|
+- 对于每个device_id和channel_no的组合,取最新的10条file_name记录(按generate_time)
|
|
|
+- 计算每条记录的不对称性(abs正、abs负)
|
|
|
+- 如果有3条或以上记录的abs正或abs负绝对值大于2,则记录该(device_id, channel_no)组合
|
|
|
+
|
|
|
+输出字段:
|
|
|
+- 设备ID
|
|
|
+- 设备名称
|
|
|
+- 通道名称
|
|
|
+- 问题结果(value>30时显示平均值;abs>2时显示10个文件的abs正和abs负值)
|
|
|
"""
|
|
|
|
|
|
import pymysql
|
|
|
@@ -94,23 +109,23 @@ def calculate_asymmetry(data):
|
|
|
"""
|
|
|
计算不对称性
|
|
|
从data中提取raw_y数组,然后计算不对称性
|
|
|
- 返回 (abs_正, abs_负)
|
|
|
+ 返回 (abs_正, abs_负, 正半轴点数量, 负半轴点数量)
|
|
|
"""
|
|
|
try:
|
|
|
# 如果data是字典,提取raw_y字段
|
|
|
if isinstance(data, dict):
|
|
|
if 'raw_y' not in data:
|
|
|
- return None, None
|
|
|
+ return None, None, None, None
|
|
|
values_list = data['raw_y']
|
|
|
elif isinstance(data, list):
|
|
|
# 如果是列表,直接使用(兼容旧代码)
|
|
|
values_list = data
|
|
|
else:
|
|
|
- return None, None
|
|
|
+ return None, None, None, None
|
|
|
|
|
|
# 确保values_list是列表
|
|
|
if not isinstance(values_list, list):
|
|
|
- return None, None
|
|
|
+ return None, None, None, None
|
|
|
|
|
|
# 转换为数值列表
|
|
|
values = []
|
|
|
@@ -122,30 +137,34 @@ def calculate_asymmetry(data):
|
|
|
continue
|
|
|
|
|
|
if len(values) == 0:
|
|
|
- return None, None
|
|
|
+ return None, None, None, None
|
|
|
|
|
|
# 分离正半轴和负半轴的值
|
|
|
positive_values = [v for v in values if v > 0]
|
|
|
negative_values = [abs(v) for v in values if v < 0] # 负半轴取绝对值
|
|
|
|
|
|
+ # 计算正半轴和负半轴的点数量
|
|
|
+ count_positive = len(positive_values)
|
|
|
+ count_negative = len(negative_values)
|
|
|
+
|
|
|
# 计算和
|
|
|
sum_positive = sum(positive_values)
|
|
|
sum_negative = sum(negative_values)
|
|
|
|
|
|
# 计算不对称性
|
|
|
- if sum_positive > 0:
|
|
|
- abs_positive = abs((sum_positive - sum_negative) / sum_positive)
|
|
|
+ if sum_negative > 0:
|
|
|
+ abs_positive = abs(sum_positive / sum_negative)
|
|
|
else:
|
|
|
abs_positive = None
|
|
|
|
|
|
- if sum_negative > 0:
|
|
|
- abs_negative = abs((sum_positive - sum_negative) / sum_negative)
|
|
|
+ if sum_positive > 0:
|
|
|
+ abs_negative = abs(sum_negative / sum_positive)
|
|
|
else:
|
|
|
abs_negative = None
|
|
|
|
|
|
- return abs_positive, abs_negative
|
|
|
+ return abs_positive, abs_negative, count_positive, count_negative
|
|
|
except Exception as e:
|
|
|
- return None, None
|
|
|
+ return None, None, None, None
|
|
|
|
|
|
def query_filtered_devices(fdfs_client=None):
|
|
|
"""
|
|
|
@@ -183,12 +202,17 @@ def query_filtered_devices(fdfs_client=None):
|
|
|
device_channel_pairs = cursor.fetchall()
|
|
|
print(f"找到 {len(device_channel_pairs)} 个device_id和channel_no的组合\n")
|
|
|
|
|
|
- # 存储符合条件的(device_id, channel_no)组合
|
|
|
- filtered_channel_list = []
|
|
|
+ # 存储符合条件的(device_id, channel_no)组合及其问题结果
|
|
|
+ # 格式: {(device_id, channel_no): {'value>30': 平均值, 'abs>2': [(生成时间, abs正, abs负, 正半轴点数量, 负半轴点数量), ...]}}
|
|
|
+ filtered_channel_dict = {}
|
|
|
+
|
|
|
+ # ===== 阶段一:筛选value>30的故障测点(基于平均值) =====
|
|
|
+ print("=" * 60)
|
|
|
+ print("阶段一:筛选value平均值>30的故障测点")
|
|
|
+ print("=" * 60)
|
|
|
|
|
|
- # 对每个device_id和channel_no组合进行处理
|
|
|
for idx, (device_id, channel_no) in enumerate(device_channel_pairs, 1):
|
|
|
- # 查询该组合的最新10条记录(按generate_time降序,按channel_no)
|
|
|
+ # 查询该组合的最新10条记录(按generate_time降序)
|
|
|
query_latest = """
|
|
|
SELECT value, generate_time
|
|
|
FROM td_d_log_result
|
|
|
@@ -205,8 +229,7 @@ def query_filtered_devices(fdfs_client=None):
|
|
|
# 如果记录数少于10条,跳过
|
|
|
continue
|
|
|
|
|
|
- # 统计value值大于20的个数
|
|
|
- count_over_20 = 0
|
|
|
+ # 计算最近10个value的平均值
|
|
|
values = []
|
|
|
|
|
|
for value_str, generate_time in records:
|
|
|
@@ -214,17 +237,81 @@ def query_filtered_devices(fdfs_client=None):
|
|
|
# value字段是varchar类型,需要转换为float
|
|
|
value = float(value_str) if value_str else 0
|
|
|
values.append(value)
|
|
|
- if value > 20:
|
|
|
- count_over_20 += 1
|
|
|
except (ValueError, TypeError):
|
|
|
# 如果转换失败,跳过该值
|
|
|
continue
|
|
|
|
|
|
- # 如果超过3个值大于20,记录该(device_id, channel_no)组合
|
|
|
- if count_over_20 > 3:
|
|
|
- filtered_channel_list.append((device_id, channel_no))
|
|
|
+ # 如果有效值数量不足,跳过
|
|
|
+ if len(values) == 0:
|
|
|
+ continue
|
|
|
+
|
|
|
+ # 计算平均值
|
|
|
+ avg_value = sum(values) / len(values)
|
|
|
+
|
|
|
+ # 如果平均值大于30,记录该(device_id, channel_no)组合(类型1:value>30)
|
|
|
+ if avg_value > 30:
|
|
|
+ key = (device_id, channel_no)
|
|
|
+ if key not in filtered_channel_dict:
|
|
|
+ filtered_channel_dict[key] = {}
|
|
|
+ filtered_channel_dict[key]['value>30'] = avg_value
|
|
|
+ print(f"[{idx}] device_id: {device_id}, channel_no: {channel_no}, "
|
|
|
+ f"平均值: {avg_value:.2f}")
|
|
|
+
|
|
|
+ # ===== 阶段二:筛选abs>2的故障测点(基于所有组合) =====
|
|
|
+ print("\n" + "=" * 60)
|
|
|
+ print("阶段二:筛选abs>2的故障测点")
|
|
|
+ print("=" * 60)
|
|
|
+
|
|
|
+ for idx, (device_id, channel_no) in enumerate(device_channel_pairs, 1):
|
|
|
+ # 查询该(device_id, channel_no)组合最近10条记录的file_name(按generate_time降序,task_id=2)
|
|
|
+ query_file_name = """
|
|
|
+ SELECT lf.file_name, lf.generate_time as file_generate_time
|
|
|
+ FROM td_d_log_file lf
|
|
|
+ WHERE lf.device_id = %s
|
|
|
+ AND lf.channel_no = %s
|
|
|
+ AND lf.task_id = '2'
|
|
|
+ ORDER BY lf.generate_time DESC
|
|
|
+ LIMIT 10
|
|
|
+ """
|
|
|
+ cursor.execute(query_file_name, (device_id, channel_no))
|
|
|
+ file_results = cursor.fetchall()
|
|
|
+
|
|
|
+ if len(file_results) < 10:
|
|
|
+ # 如果文件记录数少于10条,跳过
|
|
|
+ continue
|
|
|
+
|
|
|
+ # 统计abs正或abs负绝对值大于2的个数,同时保存所有10个文件的abs值、点数量和generate_time
|
|
|
+ count_abs_over_2 = 0
|
|
|
+ abs_values_list = [] # 保存所有10个文件的(生成时间, abs正, abs负, 正半轴点数量, 负半轴点数量)值
|
|
|
+
|
|
|
+ for file_name, file_generate_time in file_results:
|
|
|
+ if file_name:
|
|
|
+ # 解析文件并计算不对称性
|
|
|
+ data = parse_file_data(file_name, use_fdfs=(fdfs_client is not None), fdfs_client=fdfs_client)
|
|
|
+ result = calculate_asymmetry(data) if data is not None else (None, None, None, None)
|
|
|
+ abs_positive, abs_negative, count_positive, count_negative = result
|
|
|
+
|
|
|
+ # 保存abs值、点数量和generate_time
|
|
|
+ abs_values_list.append((file_generate_time, abs_positive, abs_negative, count_positive, count_negative))
|
|
|
+
|
|
|
+ # 检查abs正或abs负的绝对值是否大于2(只要其中一个大于2就算一条)
|
|
|
+ if (abs_positive is not None and abs(abs_positive) > 2) or (abs_negative is not None and abs(abs_negative) > 2):
|
|
|
+ count_abs_over_2 += 1
|
|
|
+ else:
|
|
|
+ # 如果file_name为空,也添加None值以保持列表长度
|
|
|
+ abs_values_list.append((file_generate_time, None, None, None, None))
|
|
|
+
|
|
|
+ # 如果有3条或以上记录的abs>2,记录该(device_id, channel_no)组合(类型2:abs>2)
|
|
|
+ if count_abs_over_2 >= 3:
|
|
|
+ key = (device_id, channel_no)
|
|
|
+ if key not in filtered_channel_dict:
|
|
|
+ filtered_channel_dict[key] = {}
|
|
|
+ filtered_channel_dict[key]['abs>2'] = abs_values_list
|
|
|
print(f"[{idx}] device_id: {device_id}, channel_no: {channel_no}, "
|
|
|
- f"超过20的值数量: {count_over_20}/10, 最新10个值: {values}")
|
|
|
+ f"abs>2的记录数量: {count_abs_over_2}/10")
|
|
|
+
|
|
|
+ # 转换为列表格式(用于后续处理)
|
|
|
+ filtered_channel_list = list(filtered_channel_dict.keys())
|
|
|
|
|
|
# 查询device_name
|
|
|
print("\n查询设备名称...")
|
|
|
@@ -273,69 +360,35 @@ def query_filtered_devices(fdfs_client=None):
|
|
|
for device_id, channel_no, channel_name in channel_info_results:
|
|
|
channel_info_map[(device_id, str(channel_no))] = channel_name if channel_name else '(未设置通道名称)'
|
|
|
|
|
|
- # 查询每个(device_id, channel_no)组合最近10条的file_name
|
|
|
- print("查询每个channel_no最近10条文件记录...")
|
|
|
- channel_file_map = {}
|
|
|
- if filtered_channel_list:
|
|
|
- for device_id, channel_no in filtered_channel_list:
|
|
|
- # 查询该(device_id, channel_no)组合最近10条记录的file_name(按generate_time降序,task_id=2)
|
|
|
- # 同时关联查询td_d_log_result表的generate_time
|
|
|
- query_file_name = """
|
|
|
- SELECT lf.file_name, lf.generate_time as file_generate_time, lr.generate_time as result_generate_time
|
|
|
- FROM td_d_log_file lf
|
|
|
- LEFT JOIN td_d_log_result lr ON (
|
|
|
- lf.device_id = lr.device_id
|
|
|
- AND lf.channel_no = lr.channel_no
|
|
|
- AND lf.task_id = lr.task_id
|
|
|
- AND lf.generate_time = lr.generate_time
|
|
|
- )
|
|
|
- WHERE lf.device_id = %s
|
|
|
- AND lf.channel_no = %s
|
|
|
- AND lf.task_id = '2'
|
|
|
- ORDER BY lf.generate_time DESC
|
|
|
- LIMIT 10
|
|
|
- """
|
|
|
- cursor.execute(query_file_name, (device_id, channel_no))
|
|
|
- file_results = cursor.fetchall()
|
|
|
-
|
|
|
- # 提取file_name列表,同时解析文件计算不对称性(使用FDFS路径)
|
|
|
- file_info_list = []
|
|
|
- for file_name, file_generate_time, result_generate_time in file_results:
|
|
|
- if file_name:
|
|
|
- # 解析文件并计算不对称性(使用原始FDFS路径,如果提供了fdfs_client则使用FDFS,否则从本地读取)
|
|
|
- data = parse_file_data(file_name, use_fdfs=(fdfs_client is not None), fdfs_client=fdfs_client)
|
|
|
- abs_positive, abs_negative = calculate_asymmetry(data) if data is not None else (None, None)
|
|
|
-
|
|
|
- file_info_list.append({
|
|
|
- 'file_name': file_name, # 保持原始FDFS路径
|
|
|
- 'file_generate_time': file_generate_time,
|
|
|
- 'result_generate_time': result_generate_time,
|
|
|
- 'abs_positive': abs_positive,
|
|
|
- 'abs_negative': abs_negative
|
|
|
- })
|
|
|
- channel_file_map[(device_id, channel_no)] = file_info_list
|
|
|
|
|
|
# 生成输出文件(包含时间戳)
|
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
|
output_filename = f"query_result_{timestamp}.txt"
|
|
|
output_filepath = os.path.join(os.getcwd(), output_filename)
|
|
|
|
|
|
- # 打印所有符合条件的device_id、device_name、channel_no、channel_name和最近10条file_name
|
|
|
+ # 打印所有符合条件的设备信息
|
|
|
print("\n" + "=" * 60)
|
|
|
- print("符合条件的device_id和channel_no组合列表:")
|
|
|
+ print("符合条件的故障测点列表:")
|
|
|
print("=" * 60)
|
|
|
|
|
|
# 准备输出内容(同时用于打印和写入文件)
|
|
|
output_lines = []
|
|
|
output_lines.append("=" * 60)
|
|
|
- output_lines.append("符合条件的device_id和channel_no组合列表:")
|
|
|
+ output_lines.append("符合条件的故障测点列表:")
|
|
|
output_lines.append("=" * 60)
|
|
|
output_lines.append("")
|
|
|
+ output_lines.append("字段说明:")
|
|
|
+ output_lines.append("- 设备ID: 设备标识")
|
|
|
+ output_lines.append("- 设备名称: 设备名称")
|
|
|
+ output_lines.append("- 通道名称: 通道名称")
|
|
|
+ output_lines.append("- 问题结果: value>30时显示平均值;abs>2时显示10个文件的abs正和abs负值")
|
|
|
+ output_lines.append("")
|
|
|
|
|
|
if filtered_channel_list:
|
|
|
# 按device_id和channel_no排序后打印
|
|
|
sorted_channels = sorted(filtered_channel_list, key=lambda x: (x[0], int(x[1]) if x[1].isdigit() else x[1]))
|
|
|
displayed_count = 0 # 记录实际显示的记录数
|
|
|
+
|
|
|
for device_id, channel_no in sorted_channels:
|
|
|
device_name = device_info_map.get(device_id, '(未找到设备名称)')
|
|
|
channel_name = channel_info_map.get((device_id, channel_no), '(未找到通道名称)')
|
|
|
@@ -345,65 +398,55 @@ def query_filtered_devices(fdfs_client=None):
|
|
|
continue
|
|
|
|
|
|
displayed_count += 1 # 增加显示计数
|
|
|
- file_names = channel_file_map.get((device_id, channel_no), [])
|
|
|
|
|
|
- device_info_str = f"\n设备ID: {device_id}"
|
|
|
+ # 获取问题结果
|
|
|
+ result_data = filtered_channel_dict.get((device_id, channel_no), {})
|
|
|
+
|
|
|
+ # 格式化输出
|
|
|
+ device_info_str = f"设备ID: {device_id}"
|
|
|
device_name_str = f"设备名称: {device_name}"
|
|
|
- channel_no_str = f"通道号: {channel_no}"
|
|
|
channel_name_str = f"通道名称: {channel_name}"
|
|
|
- file_count_str = f"最近10条文件记录({len(file_names)}条):"
|
|
|
|
|
|
print(device_info_str)
|
|
|
print(device_name_str)
|
|
|
- print(channel_no_str)
|
|
|
print(channel_name_str)
|
|
|
- print(file_count_str)
|
|
|
|
|
|
output_lines.append(device_info_str)
|
|
|
output_lines.append(device_name_str)
|
|
|
- output_lines.append(channel_no_str)
|
|
|
output_lines.append(channel_name_str)
|
|
|
- output_lines.append(file_count_str)
|
|
|
|
|
|
- if file_names:
|
|
|
- for idx, file_info in enumerate(file_names, 1):
|
|
|
- file_name = file_info['file_name']
|
|
|
- file_generate_time = file_info.get('file_generate_time')
|
|
|
- result_generate_time = file_info.get('result_generate_time')
|
|
|
- abs_positive = file_info.get('abs_positive')
|
|
|
- abs_negative = file_info.get('abs_negative')
|
|
|
-
|
|
|
- # 格式化输出
|
|
|
- file_time_str = str(file_generate_time) if file_generate_time else "N/A"
|
|
|
- result_time_str = str(result_generate_time) if result_generate_time else "N/A"
|
|
|
- abs_positive_str = f"{abs_positive:.6f}" if abs_positive is not None else "N/A"
|
|
|
- abs_negative_str = f"{abs_negative:.6f}" if abs_negative is not None else "N/A"
|
|
|
-
|
|
|
- file_line = f" {idx}. {file_name}"
|
|
|
- time_line = f" generate_time(td_d_log_result): {result_time_str}"
|
|
|
- abs_line = f" abs正: {abs_positive_str}, abs负: {abs_negative_str}"
|
|
|
-
|
|
|
- print(file_line)
|
|
|
- print(time_line)
|
|
|
- print(abs_line)
|
|
|
-
|
|
|
- output_lines.append(file_line)
|
|
|
- output_lines.append(time_line)
|
|
|
- output_lines.append(abs_line)
|
|
|
- else:
|
|
|
- no_file_str = " (无文件记录)"
|
|
|
- print(no_file_str)
|
|
|
- output_lines.append(no_file_str)
|
|
|
+ # 输出问题结果
|
|
|
+ problem_result_lines = []
|
|
|
+ if 'value>30' in result_data:
|
|
|
+ avg_value = result_data['value>30']
|
|
|
+ result_line = f"问题结果(value>30): 平均值 = {avg_value:.2f}"
|
|
|
+ print(result_line)
|
|
|
+ problem_result_lines.append(result_line)
|
|
|
+
|
|
|
+ if 'abs>2' in result_data:
|
|
|
+ abs_values_list = result_data['abs>2']
|
|
|
+ result_line = f"问题结果(abs>2):"
|
|
|
+ print(result_line)
|
|
|
+ problem_result_lines.append(result_line)
|
|
|
+ for idx, (generate_time, abs_pos, abs_neg, count_pos, count_neg) in enumerate(abs_values_list, 1):
|
|
|
+ time_str = str(generate_time) if generate_time else "N/A"
|
|
|
+ abs_pos_str = f"{abs_pos:.6f}" if abs_pos is not None else "N/A"
|
|
|
+ abs_neg_str = f"{abs_neg:.6f}" if abs_neg is not None else "N/A"
|
|
|
+ count_pos_str = str(count_pos) if count_pos is not None else "N/A"
|
|
|
+ count_neg_str = str(count_neg) if count_neg is not None else "N/A"
|
|
|
+ detail_line = f" 文件{idx}: generate_time = {time_str}, abs正 = {abs_pos_str}, abs负 = {abs_neg_str}, 正半轴点数量 = {count_pos_str}, 负半轴点数量 = {count_neg_str}"
|
|
|
+ print(detail_line)
|
|
|
+ problem_result_lines.append(detail_line)
|
|
|
|
|
|
- separator = "-" * 60
|
|
|
- print(separator)
|
|
|
- output_lines.append(separator)
|
|
|
+ output_lines.extend(problem_result_lines)
|
|
|
+ print("-" * 60)
|
|
|
+ output_lines.append("-" * 60)
|
|
|
|
|
|
- total_str = f"\n总计: {displayed_count} 个(device_id, channel_no)组合(已过滤掉未找到通道名称的记录)"
|
|
|
+ total_str = f"\n总计: {displayed_count} 个故障测点(已过滤掉未找到通道名称的记录)"
|
|
|
print(total_str)
|
|
|
output_lines.append(total_str)
|
|
|
else:
|
|
|
- no_result_str = "未找到符合条件的(device_id, channel_no)组合"
|
|
|
+ no_result_str = "未找到符合条件的故障测点"
|
|
|
print(no_result_str)
|
|
|
output_lines.append(no_result_str)
|
|
|
|
|
|
@@ -444,8 +487,15 @@ if __name__ == "__main__":
|
|
|
print("=" * 60)
|
|
|
print("筛选条件:")
|
|
|
print("- task_id = 2")
|
|
|
- print("- 每个device_id下channel_no的最新10条记录(按channel_no的generate_time)")
|
|
|
- print("- 这10个value值中有超过3个值大于20")
|
|
|
+ print("")
|
|
|
+ print("第一种类型(value>30):")
|
|
|
+ print(" - 每个(device_id, channel_no)组合的最新10条记录(按generate_time)")
|
|
|
+ print(" - 计算这10个value值的平均值,如果平均值大于30")
|
|
|
+ print("")
|
|
|
+ print("第二种类型(abs>2):")
|
|
|
+ print(" - 每个(device_id, channel_no)组合的最新10条file_name记录(按generate_time)")
|
|
|
+ print(" - 计算每条记录的不对称性(abs正、abs负)")
|
|
|
+ print(" - 如果有3条或以上记录的abs正或abs负绝对值大于2")
|
|
|
print("=" * 60 + "\n")
|
|
|
|
|
|
result = query_filtered_devices()
|