فهرست منبع

完善 机型的 叶轮额定转速、发电机额定转速、传动比的计算

zhouyang.xie 2 ماه پیش
والد
کامیت
f747db28f6
1فایلهای تغییر یافته به همراه698 افزوده شده و 0 حذف شده
  1. 698 0
      dataStorage_datang/info_model_turbine_v3.py

+ 698 - 0
dataStorage_datang/info_model_turbine_v3.py

@@ -0,0 +1,698 @@
+import pymysql
+import threading
+from typing import List, Dict, Any, Optional, Tuple
+import logging
+from datetime import datetime
+from collections import Counter
+import statistics
+import math
+
+# 配置日志
+logging.basicConfig(
+    level=logging.INFO,
+    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
+)
+logger = logging.getLogger(__name__)
+
+
+class ConnectionPool:
+    """MySQL数据库连接池"""
+    
+    def __init__(self, host, port, user, password, database, charset='utf8mb4', 
+                 max_connections=2, mem_quota=4 << 30):
+        self.host = host
+        self.port = port
+        self.user = user
+        self.password = password
+        self.database = database
+        self.charset = charset
+        self.max_connections = max_connections
+        self.mem_quota = mem_quota
+        
+        self._lock = threading.Lock()
+        self._connections = []
+        self._in_use = set()
+        
+    def _create_connection(self):
+        """创建新连接并设置内存配额"""
+        try:
+            conn = pymysql.connect(
+                host=self.host,
+                port=self.port,
+                user=self.user,
+                password=self.password,
+                database=self.database,
+                charset=self.charset,
+                cursorclass=pymysql.cursors.DictCursor
+            )
+            
+            # 设置会话内存配额
+            with conn.cursor() as cursor:
+                cursor.execute(f"SET SESSION tidb_mem_quota_query = {self.mem_quota}")
+                conn.commit()
+            
+            logger.debug(f"创建新数据库连接,设置内存配额为 {self.mem_quota}")
+            return conn
+        except Exception as e:
+            logger.error(f"创建数据库连接失败: {e}")
+            raise
+    
+    def get_connection(self):
+        """从连接池获取连接"""
+        with self._lock:
+            # 如果有空闲连接,返回一个
+            for conn in self._connections:
+                if conn not in self._in_use:
+                    self._in_use.add(conn)
+                    logger.debug(f"从连接池获取现有连接")
+                    return conn
+            
+            # 如果没有空闲连接但可以创建新连接
+            if len(self._connections) < self.max_connections:
+                conn = self._create_connection()
+                self._connections.append(conn)
+                self._in_use.add(conn)
+                logger.debug(f"创建新连接,当前连接数: {len(self._connections)}")
+                return conn
+            
+            # 连接池已满,等待
+            logger.warning("连接池已满,等待可用连接...")
+            import time
+            time.sleep(1)
+            return self.get_connection()
+    
+    def release_connection(self, conn):
+        """释放连接回连接池"""
+        with self._lock:
+            if conn in self._in_use:
+                self._in_use.remove(conn)
+                logger.debug(f"释放连接回连接池")
+    
+    def close_all(self):
+        """关闭所有连接"""
+        with self._lock:
+            for conn in self._connections:
+                try:
+                    conn.close()
+                except:
+                    pass
+            self._connections.clear()
+            self._in_use.clear()
+            logger.info("已关闭所有数据库连接")
+
+
+class DatabaseConfig:
+    """数据库配置类"""
+    def __init__(self, host='192.168.50.234', port=4000, user='root', 
+                 password='123456', database='wind_data', charset='utf8mb4',
+                 max_connections=2, mem_quota=4 << 30):
+        self.host = host
+        self.port = port
+        self.user = user
+        self.password = password
+        self.database = database
+        self.charset = charset
+        self.max_connections = max_connections
+        self.mem_quota = mem_quota
+
+
+class ManufacturerInfo:
+    """主机厂商信息库,用于合理性校验"""
+    
+    # 各厂商典型传动比范围(基于公开数据)
+    TRANSMISSION_RATIOS = {
+        # 直驱风机:传动比接近1
+        "金风科技": {"type": "直驱", "ratio_range": (0.95, 1.05)},
+        "远景能源": {"type": "直驱", "ratio_range": (0.95, 1.05)},
+        "明阳智能": {"type": "半直驱", "ratio_range": (30.0, 50.0)},
+        "运达股份": {"type": "双馈", "ratio_range": (70.0, 100.0)},
+        "上海电气": {"type": "双馈", "ratio_range": (70.0, 100.0)},
+        "东方电气": {"type": "双馈", "ratio_range": (70.0, 100.0)},
+        "华锐风电": {"type": "双馈", "ratio_range": (70.0, 100.0)},
+        "联合动力": {"type": "双馈", "ratio_range": (70.0, 100.0)},
+        "海装风电": {"type": "双馈", "ratio_range": (70.0, 100.0)},
+        "Vestas": {"type": "双馈", "ratio_range": (70.0, 100.0)},
+        "GE": {"type": "直驱", "ratio_range": (0.95, 1.05)},
+        "Siemens": {"type": "直驱", "ratio_range": (0.95, 1.05)},
+    }
+    
+    # 各容量等级典型叶轮转速范围(rpm)
+    ROTOR_SPEED_RANGES = {
+        1500: (15.0, 20.0),   # 1.5MW
+        2000: (14.0, 18.0),   # 2.0MW
+        2500: (13.0, 17.0),   # 2.5MW
+        3000: (12.0, 16.0),   # 3.0MW
+        3500: (11.0, 15.0),   # 3.5MW
+        4000: (10.0, 14.0),   # 4.0MW
+        5000: (9.0, 13.0),    # 5.0MW
+        6000: (8.0, 12.0),    # 6.0MW
+    }
+    
+    # 各类型风机典型发电机转速范围(rpm)
+    GENERATOR_SPEED_RANGES = {
+        "直驱": (10.0, 30.0),      # 直驱:低速发电机
+        "双馈": (1000.0, 1800.0),  # 双馈:接近同步转速
+        "半直驱": (300.0, 800.0),  # 半直驱:中速发电机
+    }
+    
+    @classmethod
+    def get_manufacturer_info(cls, manufacturer: str) -> Dict:
+        """获取厂商信息"""
+        manufacturer_lower = str(manufacturer).strip().lower() if manufacturer else ""
+        
+        for key, value in cls.TRANSMISSION_RATIOS.items():
+            if key.lower() in manufacturer_lower:
+                return value
+        
+        return {"type": "未知", "ratio_range": (0.5, 200.0)}
+    
+    @classmethod
+    def get_rotor_speed_range(cls, rated_capacity: int) -> Tuple[float, float]:
+        """根据额定容量获取合理的叶轮转速范围"""
+        if not rated_capacity:
+            return (8.0, 25.0)
+        
+        # 找到最接近的容量等级
+        capacities = sorted(cls.ROTOR_SPEED_RANGES.keys())
+        closest_capacity = min(capacities, key=lambda x: abs(x - rated_capacity))
+        return cls.ROTOR_SPEED_RANGES.get(closest_capacity, (8.0, 25.0))
+    
+    @classmethod
+    def get_generator_speed_range(cls, turbine_type: str) -> Tuple[float, float]:
+        """根据风机类型获取合理的发电机转速范围"""
+        return cls.GENERATOR_SPEED_RANGES.get(turbine_type, (0.0, 2000.0))
+
+
+class SCADADataProcessor:
+    """SCADA数据处理类,用于计算额定转速和传动比"""
+    
+    @staticmethod
+    def calculate_robust_mode(values: List[float], decimal_places: int = 1) -> float:
+        """
+        计算稳健的众数(使用核密度估计)
+        
+        Args:
+            values: 数值列表
+            decimal_places: 保留的小数位数
+            
+        Returns:
+            众数值
+        """
+        if not values:
+            return 0.0
+        
+        # 1. 数据清洗:移除异常值(使用IQR方法)
+        if len(values) >= 10:
+            q1, q3 = np.percentile(values, [25, 75])
+            iqr = q3 - q1
+            lower_bound = q1 - 1.5 * iqr
+            upper_bound = q3 + 1.5 * iqr
+            filtered_values = [v for v in values if lower_bound <= v <= upper_bound]
+            
+            if filtered_values:
+                values = filtered_values
+        
+        # 2. 对值进行四舍五入处理
+        rounded_values = [round(v, decimal_places) for v in values]
+        
+        # 3. 使用Counter统计频率
+        counter = Counter(rounded_values)
+        
+        if not counter:
+            return 0.0
+        
+        # 4. 找到最高频率
+        max_count = max(counter.values())
+        
+        # 5. 获取所有具有最高频率的值
+        modes = [value for value, count in counter.items() if count == max_count]
+        
+        # 6. 如果有多个众数,返回平均值
+        if len(modes) > 1:
+            mode_value = sum(modes) / len(modes)
+            logger.debug(f"多个众数: {modes}, 使用平均值: {mode_value}")
+        else:
+            mode_value = modes[0]
+        
+        logger.debug(f"众数统计: 值={mode_value}, 频次={max_count}, 总数据点={len(values)}")
+        return mode_value
+    
+    @staticmethod
+    def calculate_rated_parameters_with_validation(
+        rotor_speeds: List[float], 
+        gen_speeds: List[float],
+        manufacturer: str,
+        rated_capacity: int
+    ) -> Tuple[float, float, float, str]:
+        """
+        计算额定参数并进行合理性校验
+        
+        Args:
+            rotor_speeds: 叶轮转速列表
+            gen_speeds: 发电机转速列表
+            manufacturer: 制造商
+            rated_capacity: 额定容量(kW)
+            
+        Returns:
+            Tuple[float, float, float, str]: (rated_rotor_spd, rated_gen_spd, transmission_ratio, turbine_type)
+        """
+        if not rotor_speeds or not gen_speeds:
+            logger.warning(f"数据不足: 转子转速点={len(rotor_speeds)}, 发电机转速点={len(gen_speeds)}")
+            return 0.0, 0.0, 0.0, "未知"
+        
+        # 获取厂商信息
+        manu_info = ManufacturerInfo.get_manufacturer_info(manufacturer)
+        expected_type = manu_info["type"]
+        expected_ratio_range = manu_info["ratio_range"]
+        
+        # 获取合理的转速范围
+        rotor_range = ManufacturerInfo.get_rotor_speed_range(rated_capacity)
+        gen_range = ManufacturerInfo.get_generator_speed_range(expected_type)
+        
+        logger.debug(f"厂商: {manufacturer}, 预期类型: {expected_type}, "
+                    f"传动比范围: {expected_ratio_range}, "
+                    f"叶轮转速范围: {rotor_range}, 发电机转速范围: {gen_range}")
+        
+        # 第一阶段:初始计算
+        # 叶轮转速:保留1位小数
+        rated_rotor_spd = round(SCADADataProcessor.calculate_robust_mode(rotor_speeds, 1), 1)
+        
+        # 发电机转速:先计算众数,然后取整
+        gen_mode = SCADADataProcessor.calculate_robust_mode(gen_speeds, 1)
+        rated_gen_spd = int(round(gen_mode))
+        
+        # 计算传动比:保留3位小数
+        if rated_rotor_spd > 0:
+            transmission_ratio = round(rated_gen_spd / rated_rotor_spd, 3)
+        else:
+            transmission_ratio = 0.0
+        
+        # 第二阶段:合理性校验与调整
+        adjustments = []
+        
+        # 1. 校验叶轮转速
+        if not (rotor_range[0] <= rated_rotor_spd <= rotor_range[1]):
+            adjustments.append(f"叶轮转速超出范围: {rated_rotor_spd:.1f} rpm, 合理范围: {rotor_range}")
+            # 使用中位数并四舍五入到1位小数
+            rated_rotor_spd = round(float(statistics.median(rotor_speeds)), 1)
+            rated_rotor_spd = max(rotor_range[0], min(rotor_range[1], rated_rotor_spd))
+        
+        # 2. 校验发电机转速
+        if not (gen_range[0] <= rated_gen_spd <= gen_range[1]):
+            adjustments.append(f"发电机转速超出范围: {rated_gen_spd} rpm, 合理范围: {gen_range}")
+            # 使用中位数并取整
+            gen_median = float(statistics.median(gen_speeds))
+            rated_gen_spd = int(round(gen_median))
+            rated_gen_spd = int(max(gen_range[0], min(gen_range[1], rated_gen_spd)))
+        
+        # 3. 重新计算传动比
+        if rated_rotor_spd > 0:
+            transmission_ratio = round(rated_gen_spd / rated_rotor_spd, 3)
+        else:
+            transmission_ratio = 0.0
+        
+        # 4. 校验传动比
+        if not (expected_ratio_range[0] <= transmission_ratio <= expected_ratio_range[1]):
+            adjustments.append(f"传动比超出范围: {transmission_ratio:.3f}, 合理范围: {expected_ratio_range}")
+            
+            # 如果传动比异常,基于预期类型调整
+            if expected_type == "直驱":
+                # 直驱:传动比应接近1
+                transmission_ratio = 1.000
+                rated_gen_spd = int(round(rated_rotor_spd))
+            elif expected_type == "双馈":
+                # 双馈:典型传动比90:1
+                transmission_ratio = 90.000
+                rated_gen_spd = int(round(rated_rotor_spd * transmission_ratio))
+            elif expected_type == "半直驱":
+                # 半直驱:典型传动比40:1
+                transmission_ratio = 40.000
+                rated_gen_spd = int(round(rated_rotor_spd * transmission_ratio))
+        
+        # 第三阶段:最终校验与类型判断
+        # 基于最终传动比判断类型
+        if transmission_ratio <= 1.2:
+            turbine_type = "直驱"
+        elif 1.2 < transmission_ratio <= 30:
+            turbine_type = "半直驱"
+        elif 30 < transmission_ratio <= 120:
+            turbine_type = "双馈"
+        else:
+            turbine_type = "未知"
+        
+        # 如果计算的类型与预期不符,使用预期类型
+        if expected_type != "未知" and turbine_type != expected_type:
+            adjustments.append(f"类型不符: 计算={turbine_type}, 预期={expected_type}")
+            turbine_type = expected_type
+        
+        # 记录调整信息
+        if adjustments:
+            logger.info(f"参数调整: {manufacturer} {rated_capacity}kW - " + "; ".join(adjustments))
+        
+        # 最终格式化
+        # 叶轮转速:保留1位小数
+        rated_rotor_spd = round(rated_rotor_spd, 1)
+        # 发电机转速:整数
+        rated_gen_spd = int(rated_gen_spd)
+        # 传动比:保留3位小数
+        transmission_ratio = round(transmission_ratio, 3)
+        
+        logger.debug(f"最终结果: 转子转速={rated_rotor_spd:.1f} rpm, "
+                    f"发电机转速={rated_gen_spd} rpm, "
+                    f"传动比={transmission_ratio:.3f}, "
+                    f"类型={turbine_type}")
+        
+        return rated_rotor_spd, rated_gen_spd, transmission_ratio, turbine_type
+    
+    @staticmethod
+    def calculate_rated_speeds_and_ratio(
+        data: List[Dict[str, Any]], 
+        manufacturer: str = "", 
+        rated_capacity: int = 0
+    ) -> Tuple[float, float, float, str]:
+        """
+        计算额定叶轮转速、额定发电机转速、传动比和风机类型
+        
+        Args:
+            data: SCADA数据列表
+            manufacturer: 制造商(用于合理性校验)
+            rated_capacity: 额定容量(用于合理性校验)
+            
+        Returns:
+            Tuple[float, float, float, str]: (rated_rotor_spd, rated_gen_spd, transmission_ratio, turbine_type)
+        """
+        if not data:
+            return 0.0, 0.0, 0.0, "未知"
+        
+        # 提取数据
+        rotor_speeds = []
+        gen_speeds = []
+        
+        for record in data:
+            rotor_spd = record.get('rotor_spd')
+            gen_spd = record.get('gen_spd')
+            
+            if rotor_spd is not None and gen_spd is not None:
+                try:
+                    rotor_val = float(rotor_spd)
+                    gen_val = float(gen_spd)
+                    
+                    # 基本数据清洗
+                    if 0 < rotor_val < 50 and 0 < gen_val < 2500:
+                        rotor_speeds.append(rotor_val)
+                        gen_speeds.append(gen_val)
+                except (ValueError, TypeError):
+                    continue
+        
+        if not rotor_speeds or not gen_speeds:
+            logger.warning(f"有效数据不足: 转子转速点={len(rotor_speeds)}, 发电机转速点={len(gen_speeds)}")
+            return 0.0, 0.0, 0.0, "未知"
+        
+        # 计算额定参数
+        return SCADADataProcessor.calculate_rated_parameters_with_validation(
+            rotor_speeds, 
+            gen_speeds, 
+            manufacturer, 
+            rated_capacity
+        )
+
+
+# SQL语句定义(保持不变)
+CREATE_MODEL_TURBINE_TABLE_SQL = """
+CREATE TABLE IF NOT EXISTS info_model_turbine (
+    id INT AUTO_INCREMENT PRIMARY KEY,
+    no_model VARCHAR(255) NOT NULL COMMENT '机型唯一标识',
+    model VARCHAR(100) COMMENT '机型',
+    manufacturer VARCHAR(100) COMMENT '制造商',
+    rated_capacity INT COMMENT '额定容量(kW)',
+    cut_in_wind_speed DECIMAL(5, 2) COMMENT '切入风速(m/s)',
+    cut_out_wind_speed DECIMAL(5, 2) COMMENT '切出风速(m/s)',
+    rotor_diameter INT COMMENT '叶轮直径(m)',
+    hub_height DECIMAL(10, 2) COMMENT '轮毂高度(m)',
+    turbine_count INT DEFAULT 0 COMMENT '该机型风机数量',
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    UNIQUE KEY idx_no_model (no_model),
+    INDEX idx_model (model),
+    INDEX idx_manufacturer (manufacturer),
+    INDEX idx_rated_capacity (rated_capacity)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='风机机型信息表';
+"""
+
+ALTER_MODEL_TURBINE_TABLE_SQL = """
+ALTER TABLE info_model_turbine 
+ADD COLUMN IF NOT EXISTS rated_rotor_spd DECIMAL(10, 1) COMMENT '额定叶轮转速(rpm)',
+ADD COLUMN IF NOT EXISTS rated_gen_spd INT COMMENT '额定发电机转速(rpm)',
+ADD COLUMN IF NOT EXISTS transmission_ratio DECIMAL(10, 3) COMMENT '传动比',
+ADD COLUMN IF NOT EXISTS turbine_type VARCHAR(20) COMMENT '风机类型(直驱/双馈/半直驱)',
+ADD COLUMN IF NOT EXISTS calculation_time TIMESTAMP COMMENT '参数计算时间',
+ADD COLUMN IF NOT EXISTS data_points INT DEFAULT 0 COMMENT '用于计算的数据点数',
+ADD COLUMN IF NOT EXISTS calculation_status VARCHAR(20) DEFAULT 'pending' COMMENT '计算状态(pending/success/error/adjusted)',
+ADD COLUMN IF NOT EXISTS validation_info TEXT COMMENT '合理性校验信息';
+"""
+
+UPDATE_MODEL_PARAMETERS_SQL = """
+UPDATE info_model_turbine 
+SET rated_rotor_spd = %s,
+    rated_gen_spd = %s,
+    transmission_ratio = %s,
+    turbine_type = %s,
+    calculation_time = %s,
+    data_points = %s,
+    calculation_status = %s,
+    validation_info = %s,
+    updated_at = CURRENT_TIMESTAMP
+WHERE no_model = %s
+"""
+
+
+class ModelTurbineManager:
+    """风机机型信息管理器"""
+    
+    def __init__(self, db_config: DatabaseConfig):
+        self.db_config = db_config
+        self.connection_pool = None
+        self._initialize_connection_pool()
+    
+    def _initialize_connection_pool(self):
+        """初始化数据库连接池"""
+        self.connection_pool = ConnectionPool(
+            host=self.db_config.host,
+            port=self.db_config.port,
+            user=self.db_config.user,
+            password=self.db_config.password,
+            database=self.db_config.database,
+            charset=self.db_config.charset,
+            max_connections=self.db_config.max_connections,
+            mem_quota=self.db_config.mem_quota
+        )
+        logger.info(f"数据库连接池初始化完成,最大连接数: {self.db_config.max_connections}")
+    
+    # ... 其他方法保持不变 ...
+    
+    def calculate_and_update_parameters_for_model(self, no_model: str) -> Dict[str, Any]:
+        """
+        计算并更新指定机型的额定参数
+        
+        Args:
+            no_model: 机型标识
+            
+        Returns:
+            计算结果的字典
+        """
+        try:
+            # 先获取机型基本信息
+            model_info_sql = """
+            SELECT manufacturer, rated_capacity 
+            FROM info_model_turbine 
+            WHERE no_model = %s
+            """
+            
+            model_info = self.execute_query(model_info_sql, (no_model,))
+            if not model_info:
+                logger.warning(f"机型 {no_model}: 未找到基本信息")
+                return {
+                    "no_model": no_model,
+                    "success": False,
+                    "reason": "未找到机型基本信息",
+                    "data_points": 0
+                }
+            
+            manufacturer = model_info[0].get('manufacturer', '')
+            rated_capacity = model_info[0].get('rated_capacity', 0)
+            
+            # 获取该机型的SCADA数据
+            scada_data = self.get_scada_data_for_no_model(no_model)
+            
+            if not scada_data:
+                logger.warning(f"机型 {no_model}: 没有可用于计算的SCADA数据")
+                return {
+                    "no_model": no_model,
+                    "success": False,
+                    "reason": "无SCADA数据",
+                    "data_points": 0
+                }
+            
+            # 计算额定参数(带合理性校验)
+            rated_rotor_spd, rated_gen_spd, transmission_ratio, turbine_type = \
+                SCADADataProcessor.calculate_rated_speeds_and_ratio(
+                    scada_data, manufacturer, rated_capacity
+                )
+            
+            # 判断计算状态
+            if rated_rotor_spd <= 0 or transmission_ratio <= 0:
+                calculation_status = "error"
+                validation_info = "参数无效"
+                success = False
+            else:
+                # 检查是否需要调整
+                manu_info = ManufacturerInfo.get_manufacturer_info(manufacturer)
+                expected_ratio_range = manu_info["ratio_range"]
+                rotor_range = ManufacturerInfo.get_rotor_speed_range(rated_capacity)
+                gen_range = ManufacturerInfo.get_generator_speed_range(turbine_type)
+                
+                # 判断是否经过调整
+                adjustments = []
+                
+                if not (rotor_range[0] <= rated_rotor_spd <= rotor_range[1]):
+                    adjustments.append(f"叶轮转速调整: {rated_rotor_spd:.1f} rpm")
+                
+                if not (gen_range[0] <= rated_gen_spd <= gen_range[1]):
+                    adjustments.append(f"发电机转速调整: {rated_gen_spd} rpm")
+                
+                if not (expected_ratio_range[0] <= transmission_ratio <= expected_ratio_range[1]):
+                    adjustments.append(f"传动比调整: {transmission_ratio:.3f}")
+                
+                if adjustments:
+                    calculation_status = "adjusted"
+                    validation_info = "; ".join(adjustments)
+                else:
+                    calculation_status = "success"
+                    validation_info = "参数合理"
+                
+                success = True
+            
+            # 更新数据库
+            update_result = self.execute_update(
+                UPDATE_MODEL_PARAMETERS_SQL,
+                (
+                    rated_rotor_spd,
+                    rated_gen_spd,
+                    transmission_ratio,
+                    turbine_type,
+                    datetime.now(),
+                    len(scada_data),
+                    calculation_status,
+                    validation_info,
+                    no_model
+                )
+            )
+            
+            if update_result > 0:
+                log_msg = (f"机型 {no_model}: {calculation_status} - "
+                          f"叶轮转速={rated_rotor_spd:.1f} rpm, "
+                          f"发电机转速={rated_gen_spd} rpm, "
+                          f"传动比={transmission_ratio:.3f}, "
+                          f"类型={turbine_type}, "
+                          f"数据点={len(scada_data)}")
+                
+                if calculation_status == "adjusted":
+                    logger.info(log_msg + f", 调整: {validation_info}")
+                else:
+                    logger.info(log_msg)
+                
+                return {
+                    "no_model": no_model,
+                    "success": success,
+                    "status": calculation_status,
+                    "rated_rotor_spd": rated_rotor_spd,
+                    "rated_gen_spd": rated_gen_spd,
+                    "transmission_ratio": transmission_ratio,
+                    "turbine_type": turbine_type,
+                    "data_points": len(scada_data),
+                    "validation_info": validation_info
+                }
+            else:
+                logger.warning(f"机型 {no_model}: 数据库更新失败")
+                return {
+                    "no_model": no_model,
+                    "success": False,
+                    "reason": "数据库更新失败",
+                    "status": "error",
+                    "rated_rotor_spd": rated_rotor_spd,
+                    "rated_gen_spd": rated_gen_spd,
+                    "transmission_ratio": transmission_ratio,
+                    "turbine_type": turbine_type,
+                    "data_points": len(scada_data)
+                }
+                
+        except Exception as e:
+            logger.error(f"计算机型 {no_model} 参数时出错: {e}")
+            return {
+                "no_model": no_model,
+                "success": False,
+                "reason": str(e),
+                "status": "error",
+                "data_points": 0
+            }
+    
+    # ... 其他方法保持不变 ...
+
+
+def main():
+    """主函数"""
+    # 数据库配置
+    db_config = DatabaseConfig(
+        # host="106.120.102.238",
+        # port=44000,
+        host="192.168.50.234",
+        port=4000,
+        user='root',
+        password='123456',
+        database='wind_data',
+        charset='utf8mb4',
+        max_connections=2,
+        mem_quota=4 << 30  # 4GB
+    )
+    
+    # 创建管理器实例
+    manager = ModelTurbineManager(db_config)
+    
+    # 运行机型数据提取和参数计算流程
+    success = manager.run_model_extraction_pipeline(
+        recreate_table=False,  # 是否重新创建表
+        calculate_params=True   # 是否计算额定参数
+    )
+    
+    if success:
+        logger.info("风机机型数据提取和参数计算成功完成!")
+    else:
+        logger.error("风机机型数据提取和参数计算失败!")
+
+
+if __name__ == "__main__":
+    # 导入numpy用于统计计算
+    try:
+        import numpy as np
+    except ImportError:
+        logger.warning("未找到numpy库,使用简单统计方法")
+        # 定义简单的替代函数
+        def percentile(data, percentiles):
+            """简单的百分位数计算"""
+            if not data:
+                return [0, 0]
+            sorted_data = sorted(data)
+            n = len(sorted_data)
+            return [
+                sorted_data[int((n-1) * p / 100)] for p in percentiles
+            ]
+        
+        # 临时创建numpy模块
+        class NumpyStub:
+            @staticmethod
+            def percentile(data, percentiles):
+                return percentile(data, percentiles)
+        
+        np = NumpyStub()
+    
+    main()