You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

140 lines
4.7 KiB

import threading
from time import sleep
from typing import List, Dict
from mycode.DBManager import DBManager
from datetime import datetime, timedelta
from mycode.TaskManager import g_TaskM
class PollingManager:
def __init__(self):
self.DBM = DBManager()
self.brun = True
self.bUpdate = False
self.p_th = None
def parse_time(self,time_str: str) -> datetime:
"""将时间字符串转为 datetime 对象"""
if not time_str:
return None
try:
return datetime.datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')
except ValueError:
return None
def need_check(self,target: Dict) -> bool:
now = datetime.datetime.now()
period = target[5]
start_time_str = target[6]
last_time = self.parse_time(target[7])
# 不巡检的目标
if target[4] == 0 or period == 0:
return False
# 当前时间是否达到设定开始时间
if start_time_str:
try:
# 只取时间部分用于每天/每周的对比
st_hour, st_minute = map(int, start_time_str.strip().split(':')[:2])
except Exception:
return False
else:
st_hour, st_minute = 0, 0
# 当天设定执行时间点
target_time = now.replace(hour=st_hour, minute=st_minute, second=0, microsecond=0)
# 如果 last_time 已经检查过今天了,就跳过
if last_time and last_time >= target_time:
return False
if period == 1: # 每天
return now >= target_time
elif period == 2: # 每周
return now.weekday() == 0 and now >= target_time # 每周一执行
elif period == 3: # 每月
return now.day == 1 and now >= target_time # 每月1号执行
else:
return False
def should_poll(self,polling_period: int, start_time_str: str, last_time_str: str = None) -> bool:
now = datetime.now()
# 无周期,直接返回 False
if polling_period == 0:
return False
try:
# 获取比较基准时间
if last_time_str:
base_time = datetime.strptime(last_time_str, "%Y-%m-%d %H:%M:%S")
elif start_time_str:
base_time = datetime.strptime(start_time_str, "%Y-%m-%d %H:%M:%S")
if now > base_time:
return True
else:
return False
except Exception as e:
print(f"时间格式错误: {e}")
return False
if polling_period == 1:
# 每天:超过 24 小时
return (now - base_time) >= timedelta(days=1)
elif polling_period == 2:
# 每周:要到下一个“周一的那个时间点”
weekday = base_time.weekday() # 0=周一, ..., 6=周日
days_to_next_monday = (7 - weekday) % 7 or 7 # 至少是下一个周一
next_monday = base_time + timedelta(days=days_to_next_monday)
next_monday = next_monday.replace(hour=base_time.hour, minute=base_time.minute, second=base_time.second)
return now >= next_monday
elif polling_period == 3:
# 每月:下个月的 1 号,时间点与原始时间相同
year = base_time.year + (base_time.month // 12)
month = (base_time.month % 12) + 1
next_month_first = datetime(year, month, 1, base_time.hour, base_time.minute, base_time.second)
return now >= next_month_first
return False
def do_check(self,target):
print(f"巡检中: {target[2]} (类型: {target[9]})")
#创建task---并初始化待办
g_TaskM.create_polling_task(target)
def update_last_time(self, target_id):
now_str = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
strsql = "UPDATE target SET polling_last_time=%s WHERE ID=%s;"
params = (now_str,target_id)
bok,_ = self.DBM.safe_do_sql(strsql,params)
def needUpdateTargets(self):
self.bUpdate = True
def polling_th(self):
strsql = "select * from target;"
targets = self.DBM.do_select(strsql)
while self.brun:
if self.bUpdate:
targets = self.DBM.do_select(strsql)
self.bUpdate =False
for target in targets:
if self.should_poll(target[5],target[6],target[7]):
self.do_check(target)
self.update_last_time(target[0])
sleep(60 * 60) #一个小时
def run_polling(self):
self.p_th = threading.Thread(target=self.polling_th(), name=f"p_th")
self.p_th.start()
if __name__ == "__main__":
PM = PollingManager()
PM.polling_th()