Files
vision-record/scheduler.py

220 lines
6.9 KiB
Python

"""
定时任务调度模块
"""
import threading
import time
import datetime
from camera import CameraCapture
from analyzer import ImageAnalyzer
from database import db
from config import config_mgr
class VisionScheduler:
"""视觉记录调度器"""
def __init__(self):
self.camera = CameraCapture()
self.analyzer = ImageAnalyzer()
self.running = False
self.timer = None
# 统计
self.capture_count = 0
self.last_capture_time = None
self.last_analyze_time = None
self.errors = []
def start(self):
"""启动定时拍照"""
if self.running:
return {'success': False, 'error': '已在运行中'}
self.running = True
interval = config_mgr.get('capture_interval', 60)
self._schedule_next()
return {
'success': True,
'interval': interval,
'auto_analyze': config_mgr.get('auto_analyze', True)
}
def stop(self):
"""停止定时拍照"""
self.running = False
if self.timer:
self.timer.cancel()
self.timer = None
self.camera.close()
return {'success': True}
def _schedule_next(self):
"""安排下一次拍照"""
if not self.running:
return
interval = config_mgr.get('capture_interval', 60)
self.timer = threading.Timer(interval, self._capture_task)
self.timer.start()
def _capture_task(self):
"""拍照任务"""
if not self.running:
return
try:
# 拍照
result = self.camera.capture()
if result['success']:
# 记录到数据库
image_id = db.add_image(
result['path'],
date_folder=result.get('date_folder')
)
self.capture_count += 1
self.last_capture_time = datetime.datetime.now().isoformat()
# 自动分析
if config_mgr.get('auto_analyze', True):
self._analyze_task(image_id, result['path'])
else:
self.errors.append({
'time': datetime.datetime.now().isoformat(),
'error': result['error']
})
except Exception as e:
self.errors.append({
'time': datetime.datetime.now().isoformat(),
'error': str(e)
})
# 安排下一次
self._schedule_next()
def _analyze_task(self, image_id, image_path):
"""分析任务"""
try:
result = self.analyzer.analyze(image_path)
if result['success']:
# 记录事件
for event in result['events']:
db.add_event(
image_id,
event['event_type'],
event['description'],
event['confidence']
)
# 标记已分析
db.mark_image_analyzed(image_id)
self.last_analyze_time = datetime.datetime.now().isoformat()
else:
self.errors.append({
'time': datetime.datetime.now().isoformat(),
'error': f"分析失败: {result['error']}"
})
except Exception as e:
self.errors.append({
'time': datetime.datetime.now().isoformat(),
'error': str(e)
})
def capture_now(self):
"""立即拍照"""
result = self.camera.capture()
if result['success']:
image_id = db.add_image(
result['path'],
date_folder=result.get('date_folder')
)
self.capture_count += 1
self.last_capture_time = datetime.datetime.now().isoformat()
# 如果自动分析开启,立即分析
if config_mgr.get('auto_analyze', True):
threading.Thread(
target=self._analyze_task,
args=(image_id, result['path'])
).start()
return {
'success': True,
'image_id': image_id,
'path': result['path'],
'timestamp': result['timestamp'],
'date_folder': result.get('date_folder')
}
return result
def analyze_now(self, image_id):
"""立即分析指定图片"""
image = db.get_image_by_id(image_id)
if not image:
return {'success': False, 'error': '图片不存在'}
result = self.analyzer.analyze(image['path'])
if result['success']:
for event in result['events']:
db.add_event(
image_id,
event['event_type'],
event['description'],
event['confidence']
)
db.mark_image_analyzed(image_id)
self.last_analyze_time = datetime.datetime.now().isoformat()
return result
def analyze_unanalyzed(self):
"""分析所有未分析的图片"""
images = db.get_unanalyzed_images(limit=10)
results = []
for image in images:
result = self.analyzer.analyze(image['path'])
if result['success']:
for event in result['events']:
db.add_event(
image['id'],
event['event_type'],
event['description'],
event['confidence']
)
db.mark_image_analyzed(image['id'])
results.append({'image_id': image['id'], 'success': True})
else:
results.append({'image_id': image['id'], 'success': False, 'error': result['error']})
return results
def get_status(self):
"""获取调度器状态"""
return {
'running': self.running,
'interval': config_mgr.get('capture_interval', 60),
'auto_analyze': config_mgr.get('auto_analyze', True),
'capture_count': self.capture_count,
'last_capture_time': self.last_capture_time,
'last_analyze_time': self.last_analyze_time,
'recent_errors': self.errors[-5:] if self.errors else []
}
def set_interval(self, interval):
"""设置拍照间隔"""
config_mgr.set('capture_interval', interval)
if self.running:
# 重启定时器
self.stop()
self.start()
return {'success': True, 'interval': interval}
# 全局实例
scheduler = VisionScheduler()