Kaynağa Gözat

优化问题测点查询逻辑

xiangrifeng 3 ay önce
ebeveyn
işleme
a01bd0cbda
1 değiştirilmiş dosya ile 165 ekleme ve 115 silme
  1. 165 115
      query_device_filter.py

+ 165 - 115
query_device_filter.py

@@ -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()