Squashed commit of the following: commit 3dbd8d3355059b4bb39d680b1a6deff9f6277c7e Merge: 34c1604 ef2e38b Author: zkk <1007518571@qq.com> Date: Thu Dec 19 17:07:14 2024 +0800 Merge branch 'develop' of https://server.creatbot.com/Gitea/CreatBot/CreatbotMoonraker into develop commit ef2e38b870357e74fd69710fa3b09fa38604feff Author: ruipeng <1041589370@qq.com> Date: Thu Dec 19 11:01:45 2024 +0800 新增取消打印宏命令 commit 34c1604d8c5a79e95e94f13c34b5635672df47d1 Author: zkk <1007518571@qq.com> Date: Tue Dec 3 14:33:32 2024 +0800 关闭更新管理中指定节点的配置 commit d3355361dc7ff974a9fef25956adc2966ba58120 Merge: 333a789 9c00be2 Author: zkk <1007518571@qq.com> Date: Fri Nov 29 10:04:34 2024 +0800 Merge remote-tracking branch 'origin/develop' into develop commit 9c00be2f4e21f2738e4e59d92e5af4a335a258b6 Author: ruipeng <1041589370@qq.com> Date: Fri Nov 29 08:57:23 2024 +0800 gcode文件切片信息显示适配CreatWare切片软件 commit 333a789469445f5cb60d29dc7ed24a2776db3385 Author: zkk <1007518571@qq.com> Date: Tue Nov 26 18:03:29 2024 +0800 修复z高度保存的精度问题
122 lines
4.6 KiB
Python
122 lines
4.6 KiB
Python
# Klippy job state event handlers
|
|
#
|
|
# Copyright (C) 2021 Eric Callahan <arksine.code@gmail.com>
|
|
#
|
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
|
|
|
from __future__ import annotations
|
|
import logging
|
|
|
|
# Annotation imports
|
|
from typing import (
|
|
TYPE_CHECKING,
|
|
Any,
|
|
Optional,
|
|
Dict,
|
|
List,
|
|
)
|
|
from ..common import JobEvent, KlippyState
|
|
if TYPE_CHECKING:
|
|
from ..confighelper import ConfigHelper
|
|
from .klippy_apis import KlippyAPI
|
|
|
|
class JobState:
|
|
def __init__(self, config: ConfigHelper) -> None:
|
|
self.server = config.get_server()
|
|
self.last_print_stats: Dict[str, Any] = {}
|
|
self.last_event: JobEvent = JobEvent.STANDBY
|
|
self.server.register_event_handler(
|
|
"server:klippy_started", self._handle_started
|
|
)
|
|
self.server.register_event_handler(
|
|
"server:klippy_disconnect", self._handle_disconnect
|
|
)
|
|
|
|
def _handle_disconnect(self):
|
|
state = self.last_print_stats.get("state", "")
|
|
if state in ("printing", "paused"):
|
|
# set error state
|
|
self.last_print_stats["state"] = "error"
|
|
self.last_event = JobEvent.ERROR
|
|
|
|
async def _handle_started(self, state: KlippyState) -> None:
|
|
if state != KlippyState.READY:
|
|
return
|
|
kapis: KlippyAPI = self.server.lookup_component('klippy_apis')
|
|
sub: Dict[str, Optional[List[str]]] = {"print_stats": None}
|
|
try:
|
|
result = await kapis.subscribe_objects(sub, self._status_update)
|
|
except self.server.error:
|
|
logging.info("Error subscribing to print_stats")
|
|
self.last_print_stats = result.get("print_stats", {})
|
|
if "state" in self.last_print_stats:
|
|
state = self.last_print_stats["state"]
|
|
logging.info(f"Job state initialized: {state}")
|
|
|
|
async def _status_update(self, data: Dict[str, Any], _: float) -> None:
|
|
kapis: KlippyAPI = self.server.lookup_component('klippy_apis')
|
|
if 'print_stats' not in data:
|
|
return
|
|
ps = data['print_stats']
|
|
if "state" in ps:
|
|
prev_ps = dict(self.last_print_stats)
|
|
old_state: str = prev_ps['state']
|
|
new_state: str = ps['state']
|
|
new_ps = dict(self.last_print_stats)
|
|
new_ps.update(ps)
|
|
if new_state is not old_state:
|
|
if new_state == "printing":
|
|
# The "printing" state needs some special handling
|
|
# to detect "resets" and a transition from pause to resume
|
|
if self._check_resumed(prev_ps, new_ps):
|
|
new_state = "resumed"
|
|
else:
|
|
logging.info(
|
|
f"Job Started: {new_ps['filename']}"
|
|
)
|
|
new_state = "started"
|
|
logging.debug(
|
|
f"Job State Changed - Prev State: {old_state}, "
|
|
f"New State: {new_state}"
|
|
)
|
|
if new_state == "cancelled":
|
|
await kapis.run_gcode("_CANCEL_PRINT_BASE")
|
|
# NOTE: Individual job_state events are DEPRECATED. New modules
|
|
# should register handlers for "job_state: status_changed" and
|
|
# match against the JobEvent object provided.
|
|
self.server.send_event(f"job_state:{new_state}", prev_ps, new_ps)
|
|
self.last_event = JobEvent.from_string(new_state)
|
|
self.server.send_event(
|
|
"job_state:state_changed",
|
|
self.last_event,
|
|
prev_ps,
|
|
new_ps
|
|
)
|
|
if "info" in ps:
|
|
cur_layer: Optional[int] = ps["info"].get("current_layer")
|
|
if cur_layer is not None:
|
|
total: int = ps["info"].get("total_layer", 0)
|
|
self.server.send_event(
|
|
"job_state:layer_changed", cur_layer, total
|
|
)
|
|
self.last_print_stats.update(ps)
|
|
|
|
def _check_resumed(self,
|
|
prev_ps: Dict[str, Any],
|
|
new_ps: Dict[str, Any]
|
|
) -> bool:
|
|
return (
|
|
prev_ps['state'] == "paused" and
|
|
prev_ps['filename'] == new_ps['filename'] and
|
|
prev_ps['total_duration'] < new_ps['total_duration']
|
|
)
|
|
|
|
def get_last_stats(self) -> Dict[str, Any]:
|
|
return dict(self.last_print_stats)
|
|
|
|
def get_last_job_event(self) -> JobEvent:
|
|
return self.last_event
|
|
|
|
def load_component(config: ConfigHelper) -> JobState:
|
|
return JobState(config)
|