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