2 Achegas e0381ce447 ... 203199c266

Autor SHA1 Mensaxe Data
  wmy 203199c266 Merge remote-tracking branch 'origin/dev' into dev hai 3 semanas
  wmy 0c0a413ca9 1:增加 log 文件记录 hai 3 semanas
Modificáronse 5 ficheiros con 271 adicións e 182 borrados
  1. 162 16
      README_simple.md
  2. 1 1
      config.json
  3. 6 9
      logging_system.py
  4. 54 86
      main_simple.py
  5. 48 70
      smart_monitor.py

+ 162 - 16
README_simple.md

@@ -32,16 +32,24 @@ result_df = main(strategy=1, unit_filter='RO1')
 ```
 
 ### 2. 自动监控模式
-```python
-# 自动持续监控,到期触发预测
+
+**启动监控系统:**
+```bash
 python smart_monitor.py
 ```
 
-监控系统会:
-- 检查 config.json 中的 CIP 历史时间
-- 到期自动运行预测并更新下次时间
+**监控系统功能:**
+- 每5秒检查一次 config.json 中的 `cip_times.*.actual_time`
+- 检测到 `actual_time` 变化时,自动触发预测
+- 保存预测结果到 `predicted_time`(仅用于记录)
+- 自动发送预测结果到回调接口
 - 循环监控,无需人工干预
 
+**工作流程:**
+```
+修改actual_time → 监控检测 → 执行预测 → 保存predicted_time → 发送回调 → 继续监控
+```
+
 ### 3. 策略说明
 
 | 策略 | 说明 | 适用场景 |
@@ -63,20 +71,38 @@ python smart_monitor.py
   "scada": {
     "project_id": "12345"
   },
-  "cip_history": {
-    "RO1": "2025-08-05 10:00:00",
-    "RO2": "2025-07-20 15:00:00",
-    "RO3": "2025-08-01 08:00:00",
-    "RO4": "2025-07-15 12:00:00"
+  "cip_times": {
+    "RO1": {
+      "actual_time": "2025-09-11 10:30:00",
+      "predicted_time": null
+    },
+    "RO2": {
+      "actual_time": "2025-09-30 10:30:00",
+      "predicted_time": null
+    },
+    "RO3": {
+      "actual_time": "2025-09-12 10:05:00",
+      "predicted_time": null
+    },
+    "RO4": {
+      "actual_time": "2025-09-29 10:30:00",
+      "predicted_time": null
+    }
   }
 }
 ```
 
-**说明**:
-- `cip_history`:记录各机组最近一次CIP时间,用于计算预测周期
-- `api`:可选,配置后会自动推送决策结果到回调接口
+**字段说明**:
+- `cip_times`:各机组CIP时间状态
+  - `actual_time`:**实际执行的CIP时间**(修改此字段触发预测)
+  - `predicted_time`:模型预测的下次CIP时间(**仅用于记录**,不参与计算)
+- `api`:API回调配置,用于推送预测结果
 - `scada.project_id`:项目标识,用于API回调
 
+**使用说明**:
+1. **手动更新**:直接修改 `actual_time` 字段,监控系统会自动检测并触发预测
+2. **API更新**:调用提供的接口函数更新(见下方API集成部分)
+
 ## 算法原理
 
 ### 核心逻辑
@@ -158,11 +184,98 @@ analysis_logs/
 - k值计算、时间段识别、策略选择
 - API调用结果、耗时统计
 
-## 系统集成
+## API集成
+
+### 方式1:手动更新配置文件
 
-### API回调
+直接修改 `config.json` 中的 `actual_time`:
 
-配置了API的话,系统会自动推送决策结果:
+```json
+{
+  "cip_times": {
+    "RO1": {
+      "actual_time": "2025-10-12 12:00:00",  // 修改这里
+      "predicted_time": null
+    }
+  }
+}
+```
+
+监控系统会在5秒内检测到变化并自动触发预测。
+
+### 方式2:通过代码接口更新
+
+系统提供了两个接口函数,用于从外部系统获取实际CIP时间并自动触发预测:
+
+#### 1. 单个机组更新
+```python
+from smart_monitor import SmartCIPMonitor
+
+monitor = SmartCIPMonitor()
+
+# 更新RO1的实际CIP时间
+success = monitor.update_actual_cip_time('RO1', '2025-10-12 12:00:00')
+
+if success:
+    print("更新成功,系统将自动触发预测")
+```
+
+#### 2. 批量更新多个机组
+```python
+from smart_monitor import SmartCIPMonitor
+
+# 定义数据获取函数
+def get_cip_times_from_database():
+    """从数据库或其他接口获取实际CIP时间"""
+    # TODO: 实现具体的数据获取逻辑
+    return {
+        'RO1': '2025-10-12 12:00:00',
+        'RO2': '2025-10-13 08:30:00',
+        'RO3': '2025-10-14 15:45:00',
+        'RO4': '2025-10-15 10:20:00'
+    }
+
+monitor = SmartCIPMonitor()
+
+# 批量获取并更新
+results = monitor.fetch_and_update_from_api(
+    api_function=get_cip_times_from_database
+)
+
+# 查看结果
+for unit_name, success in results.items():
+    print(f"{unit_name}: {'成功' if success else '失败'}")
+```
+
+#### 3. 完整集成示例
+
+```python
+from smart_monitor import SmartCIPMonitor
+import threading
+import time
+
+# 创建监控器
+monitor = SmartCIPMonitor()
+
+# 启动监控系统(后台线程)
+monitor.running = True
+thread = threading.Thread(target=monitor.monitor_loop, daemon=True)
+thread.start()
+
+# 定期从外部接口获取并更新(主线程)
+while True:
+    # 从数据库或API获取实际CIP时间
+    results = monitor.fetch_and_update_from_api(
+        api_function=get_cip_times_from_database
+    )
+    
+    # 等待1小时后再次检查
+    time.sleep(3600)
+```
+
+### API回调推送
+
+配置了API后,预测完成会自动推送结果:
 
 **推送格式**:
 ```json
@@ -179,6 +292,19 @@ analysis_logs/
 
 失败会自动重试3次,间隔10秒。
 
+### 接口函数说明
+
+| 函数 | 功能 | 参数 | 返回值 |
+|------|------|------|--------|
+| `update_actual_cip_time` | 更新单个机组时间 | `unit_name`, `actual_time_str` | `bool` |
+| `fetch_and_update_from_api` | 批量获取并更新 | `api_url` 或 `api_function` | `dict` |
+
+**注意事项**:
+- 时间格式必须是 `YYYY-MM-DD HH:MM:SS`
+- 机组名称必须是 `RO1`, `RO2`, `RO3`, `RO4` 之一
+- 更新后无需手动触发预测,监控系统会自动处理
+- 相同的时间不会重复触发预测
+
 ### 依赖模块
 
 - `fouling_model_0922.predict.Predictor`:压差预测模型
@@ -193,4 +319,24 @@ analysis_logs/
 2. **频繁无结果**:可以降低 `min_continuous_rising` 或 `min_delay_days`
 3. **结果不合理**:检查预测模型质量,或尝试不同策略
 4. **查看详细过程**:打开 `analysis_logs/` 目录下的日志文件
+5. **配置文件格式**:确保 `actual_time` 格式为 `YYYY-MM-DD HH:MM:SS`
+6. **监控系统**:监控系统必须保持运行才能自动触发预测
+7. **API集成**:使用接口函数更新时,确保监控系统在后台运行
+
+## 常见问题
+
+**Q: 如何触发预测?**  
+A: 有两种方式:1) 手动修改 `config.json` 中的 `actual_time`;2) 使用代码接口 `update_actual_cip_time()`
+
+**Q: 更新 `actual_time` 后多久会触发预测?**  
+A: 监控系统每5秒检查一次配置文件,所以最多5秒内会触发
+
+**Q: `predicted_time` 有什么用?**  
+A: 仅用于记录模型预测结果,不参与任何计算和判断逻辑
+
+**Q: 如何避免重复预测?**  
+A: 系统自动记录已处理的时间,相同的 `actual_time` 不会重复触发
+
+**Q: 如何集成到现有系统?**  
+A: 参考"API集成"部分,使用提供的接口函数从数据库或API获取实际CIP时间并更新
 

+ 1 - 1
config.json

@@ -26,7 +26,7 @@
       "predicted_time": null
     },
     "RO2": {
-      "actual_time": "2025-09-30 10:31:00",
+      "actual_time": "2025-09-30 10:30:00",
       "predicted_time": "2025-11-14 04:00:00"
     },
     "RO3": {

+ 6 - 9
logging_system.py

@@ -76,21 +76,20 @@ class CIPAnalysisLogger:
         self.logger.info(f"开始CIP分析会话: {self.session_id}")
     
     def setup_logging(self):
-        """设置日志配置"""
+        """设置日志配置 - 只写文件,不输出控制台"""
         log_file = self.log_dir / f"{self.session_id}.log"
         
         # 创建logger
         self.logger = logging.getLogger(self.session_id)
         self.logger.setLevel(logging.INFO)
         
-        # 创建文件处理器
+        # 禁止传播到父logger,避免重复输出
+        self.logger.propagate = False
+        
+        # 创建文件处理器(只写文件)
         file_handler = logging.FileHandler(log_file, encoding='utf-8')
         file_handler.setLevel(logging.INFO)
         
-        # 创建控制台处理器
-        console_handler = logging.StreamHandler()
-        console_handler.setLevel(logging.INFO)
-        
         # 创建格式器
         formatter = logging.Formatter(
             '%(asctime)s - %(levelname)s - %(message)s',
@@ -98,12 +97,10 @@ class CIPAnalysisLogger:
         )
         
         file_handler.setFormatter(formatter)
-        console_handler.setFormatter(formatter)
         
-        # 添加处理器
+        # 添加文件处理器,不添加控制台处理器
         if not self.logger.handlers:
             self.logger.addHandler(file_handler)
-            self.logger.addHandler(console_handler)
     
     def log_input_parameters(self, strategy, start_date, prediction_start_date=None):
         """

+ 54 - 86
main_simple.py

@@ -17,6 +17,8 @@ CIP时机选择策略:
 
 import pandas as pd
 import numpy as np
+import logging
+from logging.handlers import RotatingFileHandler
 from sklearn.linear_model import LinearRegression
 from fouling_model_0922.predict import Predictor
 import warnings
@@ -29,6 +31,28 @@ import os
 
 warnings.filterwarnings('ignore', category=FutureWarning)
 
+# 日志系统配置
+logger = logging.getLogger(__name__)
+logger.setLevel(logging.INFO)
+
+# 日志输出格式
+formatter = logging.Formatter(
+    '%(asctime)s - %(threadName)s - %(levelname)s - %(message)s',
+    datefmt='%Y-%m-%d %H:%M:%S'
+)
+
+# 文件日志处理器,单个文件最大5MB,保留3个备份
+file_handler = RotatingFileHandler('main_simple.log', maxBytes=5 * 1024 * 1024, backupCount=3, encoding='utf-8')
+file_handler.setFormatter(formatter)
+
+# 控制台日志处理器
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(formatter)
+
+# 添加处理器
+logger.addHandler(file_handler)
+logger.addHandler(console_handler)
+
 # 加载配置文件
 def load_config():
     """
@@ -41,10 +65,9 @@ def load_config():
     try:
         with open(config_path, 'r', encoding='utf-8') as f:
             config = json.load(f)
-        print(f"配置文件加载成功: {config_path}")
         return config
     except Exception as e:
-        print(f"配置文件加载失败: {e}")
+        logger.error(f"配置文件加载失败: {e}")
         return None
 
 # 加载配置
@@ -101,18 +124,13 @@ def update_cip_history_in_config(result_df):
             with open(config_path, 'w', encoding='utf-8') as f:
                 json.dump(current_config, f, ensure_ascii=False, indent=2)
             
-            print(f"CIP预测时间已保存:")
-            for update in updated_units:
-                print(f"  {update}")
-            
             config = current_config
             return True
         else:
-            print("无CIP时间需要保存")
             return False
             
     except Exception as e:
-        print(f"保存CIP预测时间失败: {e}")
+        logger.error(f"保存CIP预测时间失败: {e}")
         return False
 
 def validate_data(data, name="数据"):
@@ -168,7 +186,6 @@ class OptimalCIPPredictor:
         self.window_hours = window_days * 24  # 转换为小时
         self.min_continuous_rising = min_continuous_rising
         self.min_delay_days = min_delay_days
-        print(f"预测器初始化: 窗口={window_days}天, 连续上升>={min_continuous_rising}点, 延迟>={min_delay_days}天")
     
     def calculate_sliding_k_values(self, pressure_series):
         """
@@ -444,18 +461,17 @@ def analyze_ro_unit_cip_timing(strategy=1, start_date=None, unit_filter=None):
         pd.DataFrame: 包含机组类型、CIP时机、策略说明的结果表
     """
     # 初始化日志记录器
-    logger = CIPAnalysisLogger()
+    analysis_logger = CIPAnalysisLogger()
     
     try:
         # 获取预测数据
-        print("获取预测数据...")
         try:
             all_data = Predictor().predict(start_date=start_date)  # 获取预测数据
             if all_data.empty: 
-                logger.logger.error("预测数据为空")
+                analysis_logger.logger.error("预测数据为空")
                 return pd.DataFrame()
         except Exception as e:
-            logger.logger.error(f"获取预测数据失败: {e}")
+            analysis_logger.logger.error(f"获取预测数据失败: {e}")
             return pd.DataFrame()
         
         # 将date列设置为索引
@@ -463,23 +479,11 @@ def analyze_ro_unit_cip_timing(strategy=1, start_date=None, unit_filter=None):
         
         # 获取预测数据的起始时间
         prediction_start_date = all_data.index[0].to_pydatetime()
-        print(f"预测数据起始时间: {prediction_start_date.strftime('%Y-%m-%d %H:%M:%S')}")
+        logger.info(f"预测起始: {prediction_start_date.strftime('%Y-%m-%d %H:%M:%S')}")
 
         # 记录输入参数和预测数据
-        logger.log_input_parameters(strategy, start_date, prediction_start_date)
-        logger.log_prediction_data(all_data)
-
-        # 显示配置的CIP时间状态
-        if config and 'cip_times' in config:
-            print(f"\n当前配置的CIP时间状态:")
-            for unit_name, cip_data in config['cip_times'].items():
-                if not unit_name.startswith('_'):
-                    if isinstance(cip_data, dict):
-                        actual = cip_data.get('actual_time', 'N/A')
-                        predicted = cip_data.get('predicted_time', 'N/A')
-                        print(f"  {unit_name}: 实际={actual}, 预测={predicted}")
-                    else:
-                        print(f"  {unit_name}: {cip_data}")
+        analysis_logger.log_input_parameters(strategy, start_date, prediction_start_date)
+        analysis_logger.log_prediction_data(all_data)
         
         # 确定要分析的机组
         if unit_filter:
@@ -494,32 +498,21 @@ def analyze_ro_unit_cip_timing(strategy=1, start_date=None, unit_filter=None):
             unit_days_dict[unit_id] = get_unit_days(unit_id, prediction_start_date)
         
         # 记录机组预测天数
-        logger.log_unit_days(unit_days_dict)
+        analysis_logger.log_unit_days(unit_days_dict)
         
         # 初始化预测器
         predictor = OptimalCIPPredictor(window_days=7, min_continuous_rising=3, min_delay_days=30)
         
-        # 策略说明
-        strategy_names = {
-            1: "最早时机策略",
-            2: "最晚时机策略", 
-            3: "加权平均策略",
-            4: "污染严重程度策略"
-        }
-        print(f"\n使用策略: {strategy_names.get(strategy, '未知策略')}")
-        
         # 存储分析结果
         results = []
         
         # 遍历分析各机组
         for unit_id in unit_ids:
-            print(f"\n分析机组 RO{unit_id}")
-            
             # 获取该机组的预测天数
             predict_days = unit_days_dict[unit_id]
             
             # 记录分析开始
-            logger.log_unit_analysis_start(unit_id, predict_days)
+            analysis_logger.log_unit_analysis_start(unit_id, predict_days)
             
             # 截取预测天数范围内的数据
             end_time = all_data.index[0] + timedelta(days=predict_days)
@@ -530,13 +523,11 @@ def analyze_ro_unit_cip_timing(strategy=1, start_date=None, unit_filter=None):
             pressure_columns = [col for col in truncated_data.columns if ro_name in col and 'DPT' in col and 'pred' in col]
             
             if not pressure_columns:
-                print(f"警告: 未找到{ro_name}的压差列")
+                logger.warning(f"[{ro_name}] 未找到压差列")
                 continue
             
-            print(f"找到{ro_name}压差列: {len(pressure_columns)}个")
-            
             # 记录压差数据
-            logger.log_unit_pressure_data(unit_id, truncated_data, pressure_columns)
+            analysis_logger.log_unit_pressure_data(unit_id, truncated_data, pressure_columns)
             
             # 收集各段的CIP分析结果
             cip_results = []
@@ -554,7 +545,7 @@ def analyze_ro_unit_cip_timing(strategy=1, start_date=None, unit_filter=None):
                     optimal_time, analysis = predictor.find_optimal_cip_time(pressure_series)
                     
                     # 记录分析结果
-                    logger.log_cip_analysis_result(unit_id, column, optimal_time, analysis)
+                    analysis_logger.log_cip_analysis_result(unit_id, column, optimal_time, analysis)
                     
                     if optimal_time:
                         cip_results.append({
@@ -563,13 +554,9 @@ def analyze_ro_unit_cip_timing(strategy=1, start_date=None, unit_filter=None):
                             'delay_days': analysis['delay_days'],
                             'k_value': analysis['best_k']
                         })
-                        print(f"  {column}: {optimal_time} (第{analysis['delay_days']}天, k={analysis['best_k']:.6f})")
-                    else:
-                        print(f"  {column}: 未找到CIP时机 - {analysis.get('error', '未知原因')}")
                         
                 except Exception as e:
-                    print(f"  {column}: 分析失败 - {str(e)}")
-                    logger.log_cip_analysis_result(unit_id, column, None, {"error": str(e)})
+                    analysis_logger.log_cip_analysis_result(unit_id, column, None, {"error": str(e)})
             
             # 根据策略选择最优CIP时机
             if cip_results:
@@ -579,42 +566,36 @@ def analyze_ro_unit_cip_timing(strategy=1, start_date=None, unit_filter=None):
                     'CIP时机': optimal_time,
                     '策略说明': strategy_desc
                 })
-                print(f"RO{unit_id}最优CIP时机: {optimal_time}")
-                print(f"策略: {strategy_desc}")
+                logger.info(f"[RO{unit_id}] CIP时机 → {optimal_time.strftime('%Y-%m-%d %H:%M:%S')}")
                 
-                logger.log_unit_strategy_result(unit_id, optimal_time, strategy_desc)
+                analysis_logger.log_unit_strategy_result(unit_id, optimal_time, strategy_desc)
             else:
                 results.append({
                     '机组类型': f"RO{unit_id}",
                     'CIP时机': None,
                     '策略说明': "无有效CIP时机"
                 })
-                print(f"RO{unit_id}: 未找到有效CIP时机")
+                logger.warning(f"[RO{unit_id}] 未找到有效CIP时机")
                 
-                logger.log_unit_strategy_result(unit_id, None, "无有效CIP时机")
+                analysis_logger.log_unit_strategy_result(unit_id, None, "无有效CIP时机")
     
         # 生成结果DataFrame
         result_df = pd.DataFrame(results)
         
         # 记录最终结果
-        logger.log_final_results(result_df)
+        analysis_logger.log_final_results(result_df)
         
         # 生成分析图表
-        logger.create_analysis_plots(all_data, unit_days_dict)
-        
-        print("\n" + "="*50)
-        print("分析完成")
-        print("="*50)
-        print(result_df.to_string(index=False))
+        analysis_logger.create_analysis_plots(all_data, unit_days_dict)
         
         return result_df
         
     except Exception as e:
-        logger.logger.error(f"分析过程中发生错误: {e}")
+        analysis_logger.logger.error(f"分析过程中发生错误: {e}")
         raise
     finally:
         # 确保日志记录器正确关闭
-        logger.close()
+        analysis_logger.close()
 
 def main(strategy=3, start_date=None, unit_filter=None):
     """
@@ -639,20 +620,14 @@ def main(strategy=3, start_date=None, unit_filter=None):
         result_df = main(start_date='2025-07-01 00:00:00')  # 指定时间
         result_df = main(strategy=1, unit_filter='RO1')  # 指定策略和机组
     """
-    print("RO膜污染监控与CIP预测")
-    print("=" * 50)
-    
     # 执行分析 
     result_df = analyze_ro_unit_cip_timing(strategy=strategy, start_date=start_date, unit_filter=unit_filter)
     
     # 发送回调
     if config and not result_df.empty:
-        print("\n发送决策结果...")
         callback_success = send_decision_to_callback(result_df)
-        if callback_success:
-            print("决策结果发送成功")
-        else:
-            print("决策结果发送失败")
+        if not callback_success:
+            logger.error("决策结果发送失败")
 
     return result_df
 
@@ -669,7 +644,7 @@ def send_decision_to_callback(decision_data):
         bool: 发送成功返回True,失败返回False
     """
     if config is None:
-        print("配置文件未加载")
+        logger.error("配置文件未加载")
         return False
     
     try:
@@ -703,36 +678,29 @@ def send_decision_to_callback(decision_data):
             "list": callback_list
         }
         
-        # 日志:显示待发送数据
-        log_type = callback_list[0]["type"] if callback_list else "UNKNOWN"
-        print(f"[{log_type}] 准备发送决策数据:")
-        print(f"{json.dumps(payload, indent=2, ensure_ascii=False)}")
-        
         # 发送HTTP请求(带重试机制)
         max_retries = 3
         retry_interval = 10
+        log_type = callback_list[0]["type"] if callback_list else "UNKNOWN"
         
         for attempt in range(1, max_retries + 1):
             try:
-                print(f"[{log_type}] 第{attempt}/{max_retries}次尝试发送...")
                 response = requests.post(callback_url, headers=headers, json=payload, timeout=15)
                 response.raise_for_status()
                 
-                print(f"[{log_type}] 决策数据发送成功,服务器响应: {response.text}")
+                logger.info(f"[{log_type}] 回调成功")
                 return True
                 
             except requests.exceptions.RequestException as e:
-                print(f"[{log_type}] 发送失败: {e}")
-                
                 if attempt < max_retries:
-                    print(f"[{log_type}] {retry_interval}秒后重试...")
                     time.sleep(retry_interval)
+                else:
+                    logger.error(f"[{log_type}] 回调失败(重试{max_retries}次): {e}")
         
-        print(f"[{log_type}] 所有重试均失败")
         return False
         
     except Exception as e:
-        print(f"构建回调数据时出错: {e}")
+        logger.error(f"构建回调数据时出错: {e}")
         return False
 
 if __name__ == '__main__':

+ 48 - 70
smart_monitor.py

@@ -17,10 +17,34 @@ import json
 import time
 import threading
 import pandas as pd
+import logging
+from logging.handlers import RotatingFileHandler
 from datetime import datetime
 from main_simple import main as run_cip_analysis
 from main_simple import send_decision_to_callback
 
+# 日志系统配置
+logger = logging.getLogger(__name__)
+logger.setLevel(logging.INFO)
+
+# 日志输出格式
+formatter = logging.Formatter(
+    '%(asctime)s - %(threadName)s - %(levelname)s - %(message)s',
+    datefmt='%Y-%m-%d %H:%M:%S'
+)
+
+# 文件日志处理器,单个文件最大5MB,保留3个备份
+file_handler = RotatingFileHandler('smart_monitor.log', maxBytes=5 * 1024 * 1024, backupCount=3, encoding='utf-8')
+file_handler.setFormatter(formatter)
+
+# 控制台日志处理器
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(formatter)
+
+# 添加处理器
+logger.addHandler(file_handler)
+logger.addHandler(console_handler)
+
 class SmartCIPMonitor:
     """
     CIP监控器
@@ -59,11 +83,9 @@ class SmartCIPMonitor:
         # 格式:{'RO1': '2025-12-01 12:00:00', 'RO2': '...'}
         self.last_seen_actual_times = {}
         
-        print("初始化CIP监控系统...")
         if not self.load_config():
-            print("配置加载失败")
+            logger.error("配置文件加载失败")
         else:
-            print("配置加载成功")
             self.initialize_last_seen_times()
     
     def load_config(self):
@@ -78,7 +100,7 @@ class SmartCIPMonitor:
                 self.config = json.load(f)
             return True
         except Exception as e:
-            print(f"配置文件加载失败: {e}")
+            logger.error(f"配置文件加载失败: {e}")
             return False
     
     def save_config(self):
@@ -93,7 +115,7 @@ class SmartCIPMonitor:
                 json.dump(self.config, f, ensure_ascii=False, indent=2)
             return True
         except Exception as e:
-            print(f"配置文件保存失败: {e}")
+            logger.error(f"配置文件保存失败: {e}")
             return False
     
     def initialize_last_seen_times(self):
@@ -120,8 +142,6 @@ class SmartCIPMonitor:
                 elif isinstance(unit_data, str):
                     # 兼容旧格式:直接是时间字符串
                     self.last_seen_actual_times[unit_name] = unit_data
-        
-        print(f"已初始化监控基准时间: {self.last_seen_actual_times}")
     
     def check_for_changes(self):
         """
@@ -161,9 +181,7 @@ class SmartCIPMonitor:
                     last_actual_time = self.last_seen_actual_times.get(unit_name)
                     if last_actual_time != current_actual_time:
                         changes.append((unit_name, current_actual_time))
-                        print(f"\n检测到{unit_name}实际CIP时间变化:")
-                        print(f"  旧值: {last_actual_time}")
-                        print(f"  新值: {current_actual_time}")
+                        logger.info(f"检测到{unit_name}实际CIP时间变化: 旧值={last_actual_time}, 新值={current_actual_time}")
         
         return changes
     
@@ -189,27 +207,24 @@ class SmartCIPMonitor:
         - 下次预测只由actual_time的变化触发
         """
         try:
-            print(f"\n{'='*50}")
-            print(f"开始预测 {unit_name}")
-            print(f"基于实际CIP时间: {start_date_str}")
-            print(f"{'='*50}")
+            logger.info(f"[{unit_name}] 开始预测,基于实际CIP时间: {start_date_str}")
             
             # 步骤1:调用预测逻辑
             result_df = run_cip_analysis(strategy=3, start_date=start_date_str, unit_filter=unit_name)
             
             if result_df.empty:
-                print(f"{unit_name} 预测失败: 无结果")
+                logger.warning(f"{unit_name} 预测失败: 无结果")
                 return False
             
             # 步骤2:提取该机组的结果
             unit_result = result_df[result_df['机组类型'] == unit_name]
             if unit_result.empty:
-                print(f"{unit_name} 预测失败: 结果中无此机组")
+                logger.warning(f"{unit_name} 预测失败: 结果中无此机组")
                 return False
             
             cip_time = unit_result.iloc[0]['CIP时机']
             if pd.isna(cip_time):
-                print(f"{unit_name} 预测失败: CIP时机为空")
+                logger.warning(f"{unit_name} 预测失败: CIP时机为空")
                 return False
             
             # 步骤3:保存预测时间到配置文件(仅用于记录)
@@ -234,29 +249,24 @@ class SmartCIPMonitor:
                     self.config['cip_times'][unit_name]['predicted_time'] = predicted_time_str
             
             if not self.save_config():
-                print(f"✗ {unit_name} 配置保存失败")
+                logger.error(f"[{unit_name}] 配置保存失败")
                 return False
             
-            print(f"✓ {unit_name} 预测成功")
-            print(f"  实际CIP时间: {start_date_str}")
-            print(f"  预测CIP时间: {predicted_time_str} (仅用于记录)")
+            logger.info(f"[{unit_name}] 预测成功 → {predicted_time_str}")
             
             # 步骤4:发送预测结果到回调接口
-            print(f"\n发送预测结果到回调接口...")
             try:
                 if send_decision_to_callback(result_df):
-                    print(f"✓ {unit_name} 回调发送成功")
+                    logger.info(f"[{unit_name}] 回调发送成功")
                 else:
-                    print(f"✗ {unit_name} 回调发送失败")
+                    logger.error(f"[{unit_name}] 回调发送失败")
             except Exception as callback_error:
-                print(f"✗ {unit_name} 回调发送异常: {callback_error}")
+                logger.error(f"[{unit_name}] 回调发送异常: {callback_error}")
             
             return True
                 
         except Exception as e:
-            print(f"✗ {unit_name} 预测失败: {e}")
-            import traceback
-            traceback.print_exc()
+            logger.error(f"[{unit_name}] 预测失败: {e}", exc_info=True)
             return False
     
     def process_changes(self, changes):
@@ -277,18 +287,13 @@ class SmartCIPMonitor:
         4. 短暂延时:避免频繁操作
         """
         for unit_name, new_actual_time in changes:
-            print(f"\n{'='*60}")
-            print(f"处理 {unit_name} 的实际CIP时间变化")
-            print(f"{'='*60}")
-            
             # 执行预测
             if self.predict_and_update_unit(unit_name, new_actual_time):
                 # 更新监控基准,防止重复处理
                 self.last_seen_actual_times[unit_name] = new_actual_time
-                print(f"\n✓ {unit_name} 处理完成,已更新监控基准")
-                print(f"  新的监控基准: {new_actual_time}")
+                logger.info(f"[{unit_name}] 处理完成")
             else:
-                print(f"\n✗ {unit_name} 处理失败")
+                logger.error(f"[{unit_name}] 处理失败")
             
             # 重新加载配置,确保有最新数据
             self.load_config()
@@ -314,21 +319,13 @@ class SmartCIPMonitor:
         - predicted_time的变化不会触发任何操作
         - 相同的actual_time不会重复触发
         """
-        print("\n" + "="*60)
-        print("开始监控config.json的变化")
-        print("="*60)
-        print("监控说明:")
-        print("  - 监控字段: cip_times.*.actual_time")
-        print("  - 检查频率: 每5秒")
-        print("  - 触发条件: actual_time发生变化")
-        print("  - 自动操作: 执行预测 → 保存predicted_time → 发送回调")
-        print("="*60)
+        logger.info("开始监控 config.json 变化(每5秒检查一次)")
         
         while self.running:
             try:
                 # 步骤1:重新加载配置
                 if not self.load_config():
-                    print("✗ 配置加载失败,10秒后重试...")
+                    logger.error("配置加载失败,10秒后重试...")
                     time.sleep(10)
                     continue
                 
@@ -337,16 +334,13 @@ class SmartCIPMonitor:
                 
                 if changes:
                     # 发现变化,立即处理
-                    print(f"\n检测到 {len(changes)} 个机组的actual_time变化")
                     self.process_changes(changes)
                 
                 # 步骤3:等待一段时间后再次检查
                 time.sleep(5)  # 每5秒检查一次配置文件
                     
             except Exception as e:
-                print(f"\n✗ 监控循环出错: {e}")
-                import traceback
-                traceback.print_exc()
+                logger.error(f"监控循环出错: {e}", exc_info=True)
                 time.sleep(10)  # 出错后等待10秒再继续
     
     def start(self):
@@ -354,26 +348,15 @@ class SmartCIPMonitor:
         启动监控系统
         """
         if self.running:
-            print("监控系统已在运行")
+            logger.warning("监控系统已在运行")
             return
         
-        print("\n启动CIP监控系统")
-        print("="*60)
-        print("监控模式: 检测config.json中actual_time的变化")
-        print("工作流程:")
-        print("  1. 手动修改config.json中的actual_time")
-        print("  2. 系统自动检测到变化")
-        print("  3. 基于actual_time执行预测")
-        print("  4. 保存predicted_time(仅用于记录)")
-        print("  5. 继续监控下一次变化")
-        print("="*60)
+        logger.info("CIP监控系统启动(监控 config.json 中的 actual_time 变化)")
         
         # 启动监控线程
         self.running = True
         self.monitor_thread = threading.Thread(target=self.monitor_loop, daemon=True)
         self.monitor_thread.start()
-        
-        print("\n监控系统已启动,按Ctrl+C停止")
 
         try:
             while self.running:
@@ -385,13 +368,13 @@ class SmartCIPMonitor:
         """
         停止监控系统
         """
-        print("\n停止监控系统...")
+        logger.info("停止监控系统...")
         self.running = False
         
         if self.monitor_thread and self.monitor_thread.is_alive():
             self.monitor_thread.join(timeout=5)
         
-        print("监控系统已停止")
+        logger.info("监控系统已停止")
 
 def main():
     """
@@ -399,17 +382,12 @@ def main():
     
     功能:启动监控系统
     """
-    print("CIP监控系统 - 配置文件监控模式")
-    print("="*60)
-    
     monitor = SmartCIPMonitor()
     
     try:
         monitor.start()
     except Exception as e:
-        print(f"系统运行出错: {e}")
-        import traceback
-        traceback.print_exc()
+        logger.error(f"系统运行出错: {e}", exc_info=True)
     finally:
         if monitor.running:
             monitor.stop()