Files
vision-record/scheduler.py
T

223 lines
7.1 KiB
Python
Raw Normal View History

"""
定时任务调度模块
"""
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):
"""立即分析指定图片"""
try:
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
except Exception as e:
return {'success': False, 'error': str(e)}
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()