|
@@ -1,9 +1,15 @@
|
|
|
# -*- coding: utf-8 -*-
|
|
# -*- coding: utf-8 -*-
|
|
|
"""
|
|
"""
|
|
|
-CIP监控系统
|
|
|
|
|
|
|
+CIP监控系统 - 配置文件监控模式
|
|
|
|
|
|
|
|
-功能:定时循环监控各机组CIP时机,到期自动触发预测分析
|
|
|
|
|
-监控调度由本模块负责,预测逻辑由main_simple.py实现
|
|
|
|
|
|
|
+功能:
|
|
|
|
|
+1. 监控config.json中actual_time字段的变化
|
|
|
|
|
+2. 检测到变化后,基于actual_time执行CIP预测
|
|
|
|
|
+3. 将预测结果保存到predicted_time(仅用于记录)
|
|
|
|
|
+4. 通过回调接口发送预测结果到决策系统
|
|
|
|
|
+
|
|
|
|
|
+工作流程:
|
|
|
|
|
+修改actual_time → 检测变化 → 执行预测 → 保存predicted_time → 发送回调 → 继续监控
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
import os
|
|
import os
|
|
@@ -11,22 +17,37 @@ import json
|
|
|
import time
|
|
import time
|
|
|
import threading
|
|
import threading
|
|
|
import pandas as pd
|
|
import pandas as pd
|
|
|
-from datetime import datetime, timedelta
|
|
|
|
|
|
|
+from datetime import datetime
|
|
|
from main_simple import main as run_cip_analysis
|
|
from main_simple import main as run_cip_analysis
|
|
|
|
|
+from main_simple import send_decision_to_callback
|
|
|
|
|
|
|
|
class SmartCIPMonitor:
|
|
class SmartCIPMonitor:
|
|
|
"""
|
|
"""
|
|
|
CIP监控器
|
|
CIP监控器
|
|
|
|
|
|
|
|
- 功能:
|
|
|
|
|
- - 加载和管理配置文件
|
|
|
|
|
- - 监控各机组CIP时机
|
|
|
|
|
- - 到期自动触发预测分析
|
|
|
|
|
|
|
+ 核心功能:
|
|
|
|
|
+ 1. 监控config.json中各机组的actual_time字段
|
|
|
|
|
+ 2. 检测到时间变化后,自动触发CIP预测
|
|
|
|
|
+ 3. 保存predicted_time到配置文件(仅用于记录)
|
|
|
|
|
+ 4. 发送预测结果到回调接口
|
|
|
|
|
+
|
|
|
|
|
+ 属性:
|
|
|
|
|
+ config_path: 配置文件路径
|
|
|
|
|
+ config: 配置文件内容
|
|
|
|
|
+ running: 监控运行状态
|
|
|
|
|
+ monitor_thread: 监控线程
|
|
|
|
|
+ unit_names: 机组名称列表
|
|
|
|
|
+ last_seen_actual_times: 记录上次看到的各机组actual_time,用于检测变化
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self):
|
|
def __init__(self):
|
|
|
"""
|
|
"""
|
|
|
初始化监控系统
|
|
初始化监控系统
|
|
|
|
|
+
|
|
|
|
|
+ 初始化流程:
|
|
|
|
|
+ 1. 设置配置文件路径
|
|
|
|
|
+ 2. 加载配置文件
|
|
|
|
|
+ 3. 初始化监控基准时间
|
|
|
"""
|
|
"""
|
|
|
self.config_path = os.path.join(os.path.dirname(__file__), 'config.json')
|
|
self.config_path = os.path.join(os.path.dirname(__file__), 'config.json')
|
|
|
self.config = None
|
|
self.config = None
|
|
@@ -34,11 +55,16 @@ class SmartCIPMonitor:
|
|
|
self.monitor_thread = None
|
|
self.monitor_thread = None
|
|
|
self.unit_names = ['RO1', 'RO2', 'RO3', 'RO4']
|
|
self.unit_names = ['RO1', 'RO2', 'RO3', 'RO4']
|
|
|
|
|
|
|
|
|
|
+ # 记录上次看到的actual_time,用于检测变化
|
|
|
|
|
+ # 格式:{'RO1': '2025-12-01 12:00:00', 'RO2': '...'}
|
|
|
|
|
+ self.last_seen_actual_times = {}
|
|
|
|
|
+
|
|
|
print("初始化CIP监控系统...")
|
|
print("初始化CIP监控系统...")
|
|
|
if not self.load_config():
|
|
if not self.load_config():
|
|
|
print("配置加载失败")
|
|
print("配置加载失败")
|
|
|
else:
|
|
else:
|
|
|
print("配置加载成功")
|
|
print("配置加载成功")
|
|
|
|
|
+ self.initialize_last_seen_times()
|
|
|
|
|
|
|
|
def load_config(self):
|
|
def load_config(self):
|
|
|
"""
|
|
"""
|
|
@@ -70,88 +96,112 @@ class SmartCIPMonitor:
|
|
|
print(f"配置文件保存失败: {e}")
|
|
print(f"配置文件保存失败: {e}")
|
|
|
return False
|
|
return False
|
|
|
|
|
|
|
|
- def check_all_times_past(self):
|
|
|
|
|
|
|
+ def initialize_last_seen_times(self):
|
|
|
"""
|
|
"""
|
|
|
- 检查所有机组CIP时间是否都已过期
|
|
|
|
|
-
|
|
|
|
|
- Returns:
|
|
|
|
|
- bool: 全部过期返回True,否则返回False
|
|
|
|
|
- """
|
|
|
|
|
- if not self.config or 'cip_history' not in self.config:
|
|
|
|
|
- return False
|
|
|
|
|
|
|
+ 初始化监控基准时间
|
|
|
|
|
|
|
|
- current_time = datetime.now()
|
|
|
|
|
- all_past = True
|
|
|
|
|
|
|
+ 功能:
|
|
|
|
|
+ 读取config.json中各机组当前的actual_time作为监控基准
|
|
|
|
|
+ 后续只有当actual_time与此基准不同时才触发预测
|
|
|
|
|
|
|
|
- print(f"\n当前时间: {current_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
|
|
|
- print("检查各机组CIP时间:")
|
|
|
|
|
|
|
+ 说明:
|
|
|
|
|
+ - last_seen_actual_times用于防止重复处理相同的时间
|
|
|
|
|
+ - 支持新旧配置格式兼容
|
|
|
|
|
+ """
|
|
|
|
|
+ if not self.config or 'cip_times' not in self.config:
|
|
|
|
|
+ return
|
|
|
|
|
|
|
|
for unit_name in self.unit_names:
|
|
for unit_name in self.unit_names:
|
|
|
- if unit_name in self.config['cip_history']:
|
|
|
|
|
- cip_time_str = self.config['cip_history'][unit_name]
|
|
|
|
|
- cip_time = datetime.strptime(cip_time_str, '%Y-%m-%d %H:%M:%S')
|
|
|
|
|
-
|
|
|
|
|
- is_past = cip_time <= current_time
|
|
|
|
|
- status = "已过期" if is_past else "未到时间"
|
|
|
|
|
- print(f" {unit_name}: {cip_time_str} ({status})")
|
|
|
|
|
-
|
|
|
|
|
- if not is_past:
|
|
|
|
|
- all_past = False
|
|
|
|
|
-
|
|
|
|
|
- return all_past
|
|
|
|
|
|
|
+ if unit_name in self.config['cip_times']:
|
|
|
|
|
+ unit_data = self.config['cip_times'][unit_name]
|
|
|
|
|
+ if isinstance(unit_data, dict) and 'actual_time' in unit_data:
|
|
|
|
|
+ # 新格式:{'actual_time': '...', 'predicted_time': '...'}
|
|
|
|
|
+ self.last_seen_actual_times[unit_name] = unit_data['actual_time']
|
|
|
|
|
+ elif isinstance(unit_data, str):
|
|
|
|
|
+ # 兼容旧格式:直接是时间字符串
|
|
|
|
|
+ self.last_seen_actual_times[unit_name] = unit_data
|
|
|
|
|
+
|
|
|
|
|
+ print(f"已初始化监控基准时间: {self.last_seen_actual_times}")
|
|
|
|
|
|
|
|
- def get_earliest_cip_time(self):
|
|
|
|
|
|
|
+ def check_for_changes(self):
|
|
|
"""
|
|
"""
|
|
|
- 获取最早的CIP时间
|
|
|
|
|
|
|
+ 检查actual_time是否有变化
|
|
|
|
|
|
|
|
- 用途:作为初始预测的基准时间
|
|
|
|
|
|
|
+ 功能:
|
|
|
|
|
+ 比对当前配置文件中的actual_time和上次记录的值
|
|
|
|
|
+ 发现不同则判定为有变化,需要触发预测
|
|
|
|
|
|
|
|
Returns:
|
|
Returns:
|
|
|
- datetime: 最早的CIP时间,失败返回None
|
|
|
|
|
|
|
+ list: 有变化的机组列表,格式 [(unit_name, new_actual_time), ...]
|
|
|
|
|
+ 例如:[('RO1', '2025-10-12 12:00:00'), ('RO3', '2025-10-15 08:00:00')]
|
|
|
|
|
+
|
|
|
|
|
+ 说明:
|
|
|
|
|
+ - 只有actual_time变化才会触发
|
|
|
|
|
+ - predicted_time的变化不会触发
|
|
|
"""
|
|
"""
|
|
|
- if not self.config or 'cip_history' not in self.config:
|
|
|
|
|
- return None
|
|
|
|
|
|
|
+ changes = []
|
|
|
|
|
+
|
|
|
|
|
+ if not self.config or 'cip_times' not in self.config:
|
|
|
|
|
+ return changes
|
|
|
|
|
|
|
|
- earliest_time = None
|
|
|
|
|
for unit_name in self.unit_names:
|
|
for unit_name in self.unit_names:
|
|
|
- if unit_name in self.config['cip_history']:
|
|
|
|
|
- cip_time_str = self.config['cip_history'][unit_name]
|
|
|
|
|
- cip_time = datetime.strptime(cip_time_str, '%Y-%m-%d %H:%M:%S')
|
|
|
|
|
|
|
+ if unit_name in self.config['cip_times']:
|
|
|
|
|
+ unit_data = self.config['cip_times'][unit_name]
|
|
|
|
|
+ current_actual_time = None
|
|
|
|
|
|
|
|
- if earliest_time is None or cip_time < earliest_time:
|
|
|
|
|
- earliest_time = cip_time
|
|
|
|
|
-
|
|
|
|
|
- return earliest_time
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if isinstance(unit_data, dict) and 'actual_time' in unit_data:
|
|
|
|
|
+ # 新格式:读取actual_time字段
|
|
|
|
|
+ current_actual_time = unit_data['actual_time']
|
|
|
|
|
+ elif isinstance(unit_data, str):
|
|
|
|
|
+ # 兼容旧格式:整个值就是时间
|
|
|
|
|
+ current_actual_time = unit_data
|
|
|
|
|
+
|
|
|
|
|
+ # 检查是否有变化
|
|
|
|
|
+ if current_actual_time:
|
|
|
|
|
+ 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}")
|
|
|
|
|
+
|
|
|
|
|
+ return changes
|
|
|
|
|
|
|
|
def predict_and_update_unit(self, unit_name, start_date_str):
|
|
def predict_and_update_unit(self, unit_name, start_date_str):
|
|
|
"""
|
|
"""
|
|
|
预测单个机组并保存结果到配置
|
|
预测单个机组并保存结果到配置
|
|
|
|
|
|
|
|
- 流程:
|
|
|
|
|
- 1. 调用main_simple.py进行预测
|
|
|
|
|
- 2. 解析预测结果
|
|
|
|
|
- 3. 保存到config.json
|
|
|
|
|
|
|
+ 功能:
|
|
|
|
|
+ 1. 调用main_simple.py中的预测函数
|
|
|
|
|
+ 2. 提取预测结果中的CIP时机
|
|
|
|
|
+ 3. 保存predicted_time到配置文件(仅用于记录,不参与任何计算)
|
|
|
|
|
+ 4. 发送预测结果到回调接口
|
|
|
|
|
|
|
|
Args:
|
|
Args:
|
|
|
- unit_name: str,机组名称,如'RO1'
|
|
|
|
|
- start_date_str: str,预测起始时间
|
|
|
|
|
|
|
+ unit_name: str,机组名称,如'RO1', 'RO2', 'RO3', 'RO4'
|
|
|
|
|
+ start_date_str: str,预测起始时间(即actual_time),格式'YYYY-MM-DD HH:MM:SS'
|
|
|
|
|
|
|
|
Returns:
|
|
Returns:
|
|
|
- bool: 预测成功返回True
|
|
|
|
|
|
|
+ bool: 预测成功返回True,失败返回False
|
|
|
|
|
+
|
|
|
|
|
+ 说明:
|
|
|
|
|
+ - predicted_time仅用于记录,不影响下次预测的触发
|
|
|
|
|
+ - 下次预测只由actual_time的变化触发
|
|
|
"""
|
|
"""
|
|
|
try:
|
|
try:
|
|
|
- print(f"\n预测机组: {unit_name}")
|
|
|
|
|
- print(f"起始时间: {start_date_str}")
|
|
|
|
|
|
|
+ print(f"\n{'='*50}")
|
|
|
|
|
+ print(f"开始预测 {unit_name}")
|
|
|
|
|
+ print(f"基于实际CIP时间: {start_date_str}")
|
|
|
|
|
+ print(f"{'='*50}")
|
|
|
|
|
|
|
|
- # 调用预测逻辑
|
|
|
|
|
|
|
+ # 步骤1:调用预测逻辑
|
|
|
result_df = run_cip_analysis(strategy=3, start_date=start_date_str, unit_filter=unit_name)
|
|
result_df = run_cip_analysis(strategy=3, start_date=start_date_str, unit_filter=unit_name)
|
|
|
|
|
|
|
|
if result_df.empty:
|
|
if result_df.empty:
|
|
|
print(f"{unit_name} 预测失败: 无结果")
|
|
print(f"{unit_name} 预测失败: 无结果")
|
|
|
return False
|
|
return False
|
|
|
|
|
|
|
|
- # 提取该机组的结果
|
|
|
|
|
|
|
+ # 步骤2:提取该机组的结果
|
|
|
unit_result = result_df[result_df['机组类型'] == unit_name]
|
|
unit_result = result_df[result_df['机组类型'] == unit_name]
|
|
|
if unit_result.empty:
|
|
if unit_result.empty:
|
|
|
print(f"{unit_name} 预测失败: 结果中无此机组")
|
|
print(f"{unit_name} 预测失败: 结果中无此机组")
|
|
@@ -162,179 +212,168 @@ class SmartCIPMonitor:
|
|
|
print(f"{unit_name} 预测失败: CIP时机为空")
|
|
print(f"{unit_name} 预测失败: CIP时机为空")
|
|
|
return False
|
|
return False
|
|
|
|
|
|
|
|
- # 保存到配置文件
|
|
|
|
|
- new_time_str = cip_time.strftime('%Y-%m-%d %H:%M:%S')
|
|
|
|
|
|
|
+ # 步骤3:保存预测时间到配置文件(仅用于记录)
|
|
|
|
|
+ predicted_time_str = cip_time.strftime('%Y-%m-%d %H:%M:%S')
|
|
|
|
|
|
|
|
- if unit_name not in self.config['cip_history']:
|
|
|
|
|
- print(f"配置中未找到机组 {unit_name},添加配置")
|
|
|
|
|
- self.config.setdefault('cip_history', {})[unit_name] = new_time_str
|
|
|
|
|
|
|
+ if unit_name not in self.config['cip_times']:
|
|
|
|
|
+ # 配置中不存在该机组,创建新记录
|
|
|
|
|
+ self.config['cip_times'][unit_name] = {
|
|
|
|
|
+ 'actual_time': start_date_str,
|
|
|
|
|
+ 'predicted_time': predicted_time_str
|
|
|
|
|
+ }
|
|
|
else:
|
|
else:
|
|
|
- self.config['cip_history'][unit_name] = new_time_str
|
|
|
|
|
|
|
+ # 更新预测时间,保持actual_time不变
|
|
|
|
|
+ if not isinstance(self.config['cip_times'][unit_name], dict):
|
|
|
|
|
+ # 兼容旧格式:转换为新格式
|
|
|
|
|
+ self.config['cip_times'][unit_name] = {
|
|
|
|
|
+ 'actual_time': self.config['cip_times'][unit_name],
|
|
|
|
|
+ 'predicted_time': predicted_time_str
|
|
|
|
|
+ }
|
|
|
|
|
+ else:
|
|
|
|
|
+ # 只更新predicted_time,不修改actual_time
|
|
|
|
|
+ self.config['cip_times'][unit_name]['predicted_time'] = predicted_time_str
|
|
|
|
|
|
|
|
- if self.save_config():
|
|
|
|
|
- print(f"{unit_name} 预测成功: {new_time_str}")
|
|
|
|
|
- return True
|
|
|
|
|
- else:
|
|
|
|
|
- print(f"{unit_name} 配置保存失败")
|
|
|
|
|
|
|
+ if not self.save_config():
|
|
|
|
|
+ print(f"✗ {unit_name} 配置保存失败")
|
|
|
return False
|
|
return False
|
|
|
|
|
+
|
|
|
|
|
+ print(f"✓ {unit_name} 预测成功")
|
|
|
|
|
+ print(f" 实际CIP时间: {start_date_str}")
|
|
|
|
|
+ print(f" 预测CIP时间: {predicted_time_str} (仅用于记录)")
|
|
|
|
|
+
|
|
|
|
|
+ # 步骤4:发送预测结果到回调接口
|
|
|
|
|
+ print(f"\n发送预测结果到回调接口...")
|
|
|
|
|
+ try:
|
|
|
|
|
+ if send_decision_to_callback(result_df):
|
|
|
|
|
+ print(f"✓ {unit_name} 回调发送成功")
|
|
|
|
|
+ else:
|
|
|
|
|
+ print(f"✗ {unit_name} 回调发送失败")
|
|
|
|
|
+ except Exception as callback_error:
|
|
|
|
|
+ print(f"✗ {unit_name} 回调发送异常: {callback_error}")
|
|
|
|
|
+
|
|
|
|
|
+ return True
|
|
|
|
|
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
- print(f"{unit_name} 预测失败: {e}")
|
|
|
|
|
|
|
+ print(f"✗ {unit_name} 预测失败: {e}")
|
|
|
|
|
+ import traceback
|
|
|
|
|
+ traceback.print_exc()
|
|
|
return False
|
|
return False
|
|
|
|
|
|
|
|
- def run_initial_cycle(self):
|
|
|
|
|
|
|
+ def process_changes(self, changes):
|
|
|
"""
|
|
"""
|
|
|
- 执行初始预测循环
|
|
|
|
|
|
|
+ 处理检测到的actual_time变化
|
|
|
|
|
|
|
|
- 功能:预测所有机组的CIP时机并保存
|
|
|
|
|
-
|
|
|
|
|
- Returns:
|
|
|
|
|
- bool: 至少一个机组预测成功返回True
|
|
|
|
|
- """
|
|
|
|
|
- print("\n执行初始预测循环...")
|
|
|
|
|
-
|
|
|
|
|
- # 获取起始时间
|
|
|
|
|
- earliest_time = self.get_earliest_cip_time()
|
|
|
|
|
- if not earliest_time:
|
|
|
|
|
- print("无法获取起始时间")
|
|
|
|
|
- return False
|
|
|
|
|
-
|
|
|
|
|
- start_date_str = earliest_time.strftime('%Y-%m-%d %H:%M:%S')
|
|
|
|
|
- success_count = 0
|
|
|
|
|
-
|
|
|
|
|
- # 逐个预测各机组
|
|
|
|
|
- for unit_name in self.unit_names:
|
|
|
|
|
- if self.predict_and_update_unit(unit_name, start_date_str):
|
|
|
|
|
- success_count += 1
|
|
|
|
|
- self.load_config() # 重新加载配置获取最新时间
|
|
|
|
|
- time.sleep(2)
|
|
|
|
|
-
|
|
|
|
|
- print(f"\n初始循环完成: {success_count}/{len(self.unit_names)} 个机组成功")
|
|
|
|
|
- return success_count > 0
|
|
|
|
|
-
|
|
|
|
|
- def get_next_trigger(self):
|
|
|
|
|
- """
|
|
|
|
|
- 获取下一个需要触发的时间和机组
|
|
|
|
|
-
|
|
|
|
|
- 逻辑:
|
|
|
|
|
- 1. 如果有时间已到期(或1分钟内到期),立即返回该机组
|
|
|
|
|
- 2. 否则返回最近的未来时间点
|
|
|
|
|
|
|
+ 功能:
|
|
|
|
|
+ 遍历所有检测到的变化,逐个执行预测并更新监控基准
|
|
|
|
|
|
|
|
- Returns:
|
|
|
|
|
- tuple: (next_time, next_unit),时间和机组名称
|
|
|
|
|
|
|
+ Args:
|
|
|
|
|
+ changes: list,变化列表,格式 [(unit_name, new_actual_time), ...]
|
|
|
|
|
+ 例如:[('RO1', '2025-10-12 12:00:00')]
|
|
|
|
|
+
|
|
|
|
|
+ 处理流程:
|
|
|
|
|
+ 1. 执行预测:调用predict_and_update_unit
|
|
|
|
|
+ 2. 更新监控基准:将新的actual_time记录到last_seen_actual_times
|
|
|
|
|
+ 3. 重新加载配置:确保获取最新数据
|
|
|
|
|
+ 4. 短暂延时:避免频繁操作
|
|
|
"""
|
|
"""
|
|
|
- if not self.config or 'cip_history' not in self.config:
|
|
|
|
|
- return None, None
|
|
|
|
|
-
|
|
|
|
|
- current_time = datetime.now()
|
|
|
|
|
- next_time = None
|
|
|
|
|
- next_unit = None
|
|
|
|
|
-
|
|
|
|
|
- for unit_name in self.unit_names:
|
|
|
|
|
- if unit_name in self.config['cip_history']:
|
|
|
|
|
- cip_time_str = self.config['cip_history'][unit_name]
|
|
|
|
|
- cip_time = datetime.strptime(cip_time_str, '%Y-%m-%d %H:%M:%S')
|
|
|
|
|
-
|
|
|
|
|
- # 时间已到或即将到达(1分钟内),立即触发
|
|
|
|
|
- if cip_time <= current_time + timedelta(minutes=1):
|
|
|
|
|
- return cip_time, unit_name
|
|
|
|
|
-
|
|
|
|
|
- # 记录最近的未来时间
|
|
|
|
|
- if next_time is None or cip_time < next_time:
|
|
|
|
|
- next_time = cip_time
|
|
|
|
|
- next_unit = unit_name
|
|
|
|
|
-
|
|
|
|
|
- return next_time, next_unit
|
|
|
|
|
|
|
+ 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}")
|
|
|
|
|
+ else:
|
|
|
|
|
+ print(f"\n✗ {unit_name} 处理失败")
|
|
|
|
|
+
|
|
|
|
|
+ # 重新加载配置,确保有最新数据
|
|
|
|
|
+ self.load_config()
|
|
|
|
|
+ time.sleep(2) # 短暂延时,避免频繁操作
|
|
|
|
|
|
|
|
def monitor_loop(self):
|
|
def monitor_loop(self):
|
|
|
"""
|
|
"""
|
|
|
监控主循环
|
|
监控主循环
|
|
|
|
|
|
|
|
功能:
|
|
功能:
|
|
|
- 1. 定期检查各机组CIP时间
|
|
|
|
|
- 2. 到期自动触发预测
|
|
|
|
|
- 3. 调整检查频率
|
|
|
|
|
|
|
+ 1. 定期重新加载config.json(每5秒)
|
|
|
|
|
+ 2. 检查actual_time是否有变化
|
|
|
|
|
+ 3. 发现变化后自动触发预测
|
|
|
|
|
+ 4. 发送预测结果到回调接口
|
|
|
|
|
+
|
|
|
|
|
+ 监控频率:
|
|
|
|
|
+ - 每5秒检查一次配置文件
|
|
|
|
|
+ - 发现变化立即处理
|
|
|
|
|
+ - 处理失败不影响后续监控
|
|
|
|
|
+
|
|
|
|
|
+ 说明:
|
|
|
|
|
+ - 只监控actual_time字段的变化
|
|
|
|
|
+ - predicted_time的变化不会触发任何操作
|
|
|
|
|
+ - 相同的actual_time不会重复触发
|
|
|
"""
|
|
"""
|
|
|
- print("\n开始监控循环...")
|
|
|
|
|
|
|
+ print("\n" + "="*60)
|
|
|
|
|
+ print("开始监控config.json的变化")
|
|
|
|
|
+ print("="*60)
|
|
|
|
|
+ print("监控说明:")
|
|
|
|
|
+ print(" - 监控字段: cip_times.*.actual_time")
|
|
|
|
|
+ print(" - 检查频率: 每5秒")
|
|
|
|
|
+ print(" - 触发条件: actual_time发生变化")
|
|
|
|
|
+ print(" - 自动操作: 执行预测 → 保存predicted_time → 发送回调")
|
|
|
|
|
+ print("="*60)
|
|
|
|
|
|
|
|
while self.running:
|
|
while self.running:
|
|
|
try:
|
|
try:
|
|
|
- # 重新加载配置
|
|
|
|
|
- self.load_config()
|
|
|
|
|
|
|
+ # 步骤1:重新加载配置
|
|
|
|
|
+ if not self.load_config():
|
|
|
|
|
+ print("✗ 配置加载失败,10秒后重试...")
|
|
|
|
|
+ time.sleep(10)
|
|
|
|
|
+ continue
|
|
|
|
|
|
|
|
- # 获取下一个触发时间
|
|
|
|
|
- # TODO 上一次实际CIP时间,传入到模型得到预测的 CIP时间,
|
|
|
|
|
- # 改为主动读取某个表或者接口获取该实际 CIP 时间,找梦阳
|
|
|
|
|
- next_time, next_unit = self.get_next_trigger()
|
|
|
|
|
|
|
+ # 步骤2:检查是否有变化
|
|
|
|
|
+ changes = self.check_for_changes()
|
|
|
|
|
|
|
|
- if next_time and next_unit:
|
|
|
|
|
- current_time = datetime.now()
|
|
|
|
|
- time_diff = (next_time - current_time).total_seconds()
|
|
|
|
|
-
|
|
|
|
|
- if time_diff <= 60:
|
|
|
|
|
- # 1分钟内,立即触发预测
|
|
|
|
|
- print(f"\n触发 {next_unit} CIP预测")
|
|
|
|
|
-
|
|
|
|
|
- current_time_str = current_time.strftime('%Y-%m-%d %H:%M:%S')
|
|
|
|
|
- self.predict_and_update_unit(next_unit, current_time_str)
|
|
|
|
|
-
|
|
|
|
|
- time.sleep(5)
|
|
|
|
|
- else:
|
|
|
|
|
- # 显示等待信息
|
|
|
|
|
- hours = int(time_diff // 3600)
|
|
|
|
|
- minutes = int((time_diff % 3600) // 60)
|
|
|
|
|
- print(f"下一个触发: {next_unit} ({next_time.strftime('%Y-%m-%d %H:%M:%S')})")
|
|
|
|
|
- print(f"剩余时间: {hours}小时{minutes}分钟")
|
|
|
|
|
-
|
|
|
|
|
- # 等待:距离时间越近,检查频率越高
|
|
|
|
|
- if time_diff > 3600:
|
|
|
|
|
- sleep_time = 600 # 超过1小时,每10分钟检查
|
|
|
|
|
- elif time_diff > 300:
|
|
|
|
|
- sleep_time = 60 # 超过5分钟,每分钟检查
|
|
|
|
|
- else:
|
|
|
|
|
- sleep_time = 10 # 5分钟内,每10秒检查
|
|
|
|
|
-
|
|
|
|
|
- time.sleep(sleep_time)
|
|
|
|
|
- else:
|
|
|
|
|
- print("没有找到有效的CIP时间,执行初始循环...")
|
|
|
|
|
- self.run_initial_cycle()
|
|
|
|
|
- time.sleep(30)
|
|
|
|
|
|
|
+ if changes:
|
|
|
|
|
+ # 发现变化,立即处理
|
|
|
|
|
+ print(f"\n检测到 {len(changes)} 个机组的actual_time变化")
|
|
|
|
|
+ self.process_changes(changes)
|
|
|
|
|
+
|
|
|
|
|
+ # 步骤3:等待一段时间后再次检查
|
|
|
|
|
+ time.sleep(5) # 每5秒检查一次配置文件
|
|
|
|
|
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
- print(f"监控循环出错: {e}")
|
|
|
|
|
- time.sleep(30)
|
|
|
|
|
|
|
+ print(f"\n✗ 监控循环出错: {e}")
|
|
|
|
|
+ import traceback
|
|
|
|
|
+ traceback.print_exc()
|
|
|
|
|
+ time.sleep(10) # 出错后等待10秒再继续
|
|
|
|
|
|
|
|
def start(self):
|
|
def start(self):
|
|
|
"""
|
|
"""
|
|
|
启动监控系统
|
|
启动监控系统
|
|
|
-
|
|
|
|
|
- 流程:
|
|
|
|
|
- 1. 检查所有机组时间是否过期
|
|
|
|
|
- 2. 如果过期则执行初始预测
|
|
|
|
|
- 3. 启动监控线程
|
|
|
|
|
"""
|
|
"""
|
|
|
if self.running:
|
|
if self.running:
|
|
|
print("监控系统已在运行")
|
|
print("监控系统已在运行")
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
print("\n启动CIP监控系统")
|
|
print("\n启动CIP监控系统")
|
|
|
- print("="*50)
|
|
|
|
|
-
|
|
|
|
|
- # 检查是否需要初始预测
|
|
|
|
|
- if self.check_all_times_past():
|
|
|
|
|
- print("\n所有机组时间已过期,执行初始预测...")
|
|
|
|
|
- if not self.run_initial_cycle():
|
|
|
|
|
- print("初始预测失败")
|
|
|
|
|
- return
|
|
|
|
|
- else:
|
|
|
|
|
- print("\n进入监控模式...")
|
|
|
|
|
|
|
+ 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)
|
|
|
|
|
|
|
|
# 启动监控线程
|
|
# 启动监控线程
|
|
|
self.running = True
|
|
self.running = True
|
|
|
self.monitor_thread = threading.Thread(target=self.monitor_loop, daemon=True)
|
|
self.monitor_thread = threading.Thread(target=self.monitor_loop, daemon=True)
|
|
|
self.monitor_thread.start()
|
|
self.monitor_thread.start()
|
|
|
|
|
|
|
|
- print("\n监控系统已启动")
|
|
|
|
|
|
|
+ print("\n监控系统已启动,按Ctrl+C停止")
|
|
|
|
|
|
|
|
try:
|
|
try:
|
|
|
while self.running:
|
|
while self.running:
|
|
@@ -360,8 +399,8 @@ def main():
|
|
|
|
|
|
|
|
功能:启动监控系统
|
|
功能:启动监控系统
|
|
|
"""
|
|
"""
|
|
|
- print("CIP监控系统")
|
|
|
|
|
- print("="*50)
|
|
|
|
|
|
|
+ print("CIP监控系统 - 配置文件监控模式")
|
|
|
|
|
+ print("="*60)
|
|
|
|
|
|
|
|
monitor = SmartCIPMonitor()
|
|
monitor = SmartCIPMonitor()
|
|
|
|
|
|
|
@@ -369,6 +408,8 @@ def main():
|
|
|
monitor.start()
|
|
monitor.start()
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
print(f"系统运行出错: {e}")
|
|
print(f"系统运行出错: {e}")
|
|
|
|
|
+ import traceback
|
|
|
|
|
+ traceback.print_exc()
|
|
|
finally:
|
|
finally:
|
|
|
if monitor.running:
|
|
if monitor.running:
|
|
|
monitor.stop()
|
|
monitor.stop()
|