-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
139 lines (116 loc) · 5.04 KB
/
Copy pathmain.py
File metadata and controls
139 lines (116 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import time
import threading
import signal
import importlib
from utils import clear_console
from tg_bot.bot import run_telegram_bot
from printer.status import (
get_print_stats, get_display_status, get_idle_timeout,
get_extruder, get_heater_bed, format_time
)
from printer.watcher import PrintWatcher
from printer import spaghetti_detector
from printer.cleanup import cleanup_old_images
from printer.detector.service import TEMP_DIR
from utils.logger import setup_logging, get_logger
import sys
# Set up logging
logger = setup_logging()
logger = get_logger('main')
stop_event = threading.Event()
def console_monitor():
while not stop_event.is_set():
try:
ps = get_print_stats()
ds = get_display_status()
idle = get_idle_timeout()
ex = get_extruder()
hb = get_heater_bed()
state = ps.get("state", "unknown")
filename = ps.get("filename", "-")
printing_time = idle.get("printing_time", 0)
progress = ds.get("progress", 0) * 100
message = ds.get("message", "")
extruder_temp = ex.get("temperature", 0)
extruder_target = ex.get("target", 0)
bed_temp = hb.get("temperature", 0)
bed_target = hb.get("target", 0)
clear_console()
print("="*40)
print(f"Файл: {filename}")
print(f"Статус: {state}")
print(f"Прогресс: {progress:.1f}%")
print(f"Время печати: {format_time(printing_time)}")
print(f"Экструдер: {extruder_temp:.1f}/{extruder_target:.1f} °C")
print(f"Стол: {bed_temp:.1f}/{bed_target:.1f} °C")
if message:
print(f"Сообщение: {message}")
print("="*40)
except Exception as e:
logger.error(f"Console monitor error: {e}")
clear_console()
print(f"Ошибка консоли: {e}")
if stop_event.wait(timeout=2):
break
def run_telegram_thread():
try:
run_telegram_bot()
except Exception as e:
logger.error(f"Telegram bot thread error: {e}")
def run_watcher_thread(watcher: PrintWatcher):
try:
watcher.run()
except Exception as e:
logger.error(f"Print watcher thread error: {e}")
def run_spaghetti_thread():
try:
# запускаем run_spaghetti_detector в отдельном потоке
spaghetti_detector.run_spaghetti_detector()
except Exception as e:
logger.error(f"Spaghetti detector thread error: {e}")
def _graceful_shutdown(watcher_instance=None):
logger.info("Shutting down...")
stop_event.set()
# Попытка корректно остановить watcher, если есть метод stop()
try:
if watcher_instance and hasattr(watcher_instance, "stop"):
watcher_instance.stop()
except Exception as e:
logger.error(f"Error stopping watcher: {e}")
# Попытка остановить детектор
try:
detector = spaghetti_detector.get_detector_instance()
if detector and hasattr(detector, "stop"):
detector.stop()
except Exception as e:
logger.error(f"Error stopping spaghetti detector: {e}")
logger.info("Shutdown complete")
if __name__ == "__main__":
try:
removed = cleanup_old_images(TEMP_DIR, max_age_hours=72)
logger.info(f"Cleaned up old snapshots: removed {removed} photos")
print(f"Очистка старых снимков: удалено {removed} фото")
# Telegram bot
telegram_thread = threading.Thread(target=run_telegram_thread, daemon=True, name="TelegramBot")
telegram_thread.start()
# Создаём watcher и запускаем его в потоке, чтобы иметь ссылку для .stop()
watcher = PrintWatcher()
watcher_thread = threading.Thread(target=run_watcher_thread, args=(watcher,), daemon=True, name="PrintWatcher")
watcher_thread.start()
# Spaghetti detector — запускаем в отдельном потоке (safety: если функция блокирует)
spaghetti_thread = threading.Thread(target=run_spaghetti_thread, daemon=True, name="SpaghettiDetector")
spaghetti_thread.start()
# Обработчик сигнала SIGINT для корректного завершения
def _on_sigint(signum, frame):
_graceful_shutdown(watcher_instance=watcher)
signal.signal(signal.SIGINT, _on_sigint)
signal.signal(signal.SIGTERM, _on_sigint)
# Запускаем монитор в основном потоке
console_monitor()
except KeyboardInterrupt:
logger.info("Received keyboard interrupt")
except Exception as e:
logger.error(f"Main application error: {e}")
print(f"Critical error: {e}", file=sys.stderr)
finally:
_graceful_shutdown(watcher_instance=watcher)