mirror of
https://github.com/Klipper3d/klipper.git
synced 2025-07-15 10:47:52 -06:00
webhooks: Require a subscription to receive gcode output
Add a new "gcode/subscribe_output" webhook endpoint to subscribe to gcode output. Only client connections that subscribe to the gcode output will receive that output. This also moves all the gcode webhooks from gcode.py to webhooks.py and arranges for gcode.py to be initialized prior to webhooks.py. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
568393c941
commit
16a53e6918
3 changed files with 53 additions and 32 deletions
|
@ -45,12 +45,16 @@ class Sentinel:
|
|||
|
||||
class WebRequest:
|
||||
error = WebRequestError
|
||||
def __init__(self, base_request):
|
||||
def __init__(self, client_conn, base_request):
|
||||
self.client_conn = client_conn
|
||||
self.id = base_request['id']
|
||||
self.path = base_request['path']
|
||||
self.args = base_request['args']
|
||||
self.response = None
|
||||
|
||||
def get_client_connection(self):
|
||||
return self.client_conn
|
||||
|
||||
def get(self, item, default=Sentinel):
|
||||
if item not in self.args:
|
||||
if default == Sentinel:
|
||||
|
@ -170,6 +174,9 @@ class ClientConnection:
|
|||
pass
|
||||
self.server.pop_client(self.uid)
|
||||
|
||||
def is_closed(self):
|
||||
return self.fd_handle is None
|
||||
|
||||
def process_received(self, eventtime):
|
||||
try:
|
||||
data = self.sock.recv(4096)
|
||||
|
@ -191,7 +198,7 @@ class ClientConnection:
|
|||
logging.debug(
|
||||
"webhooks: Request received: %s" % (req))
|
||||
try:
|
||||
web_request = WebRequest(json_loads_byteified(req))
|
||||
web_request = WebRequest(self, json_loads_byteified(req))
|
||||
except Exception:
|
||||
logging.exception(
|
||||
"webhooks: Error decoding Server Request %s"
|
||||
|
@ -256,22 +263,12 @@ class WebHooks:
|
|||
self.sconn = ServerSocket(self, printer)
|
||||
|
||||
# Register Events
|
||||
printer.register_event_handler(
|
||||
"klippy:connect", self._handle_connect)
|
||||
printer.register_event_handler(
|
||||
"klippy:shutdown", self._notify_shutdown)
|
||||
|
||||
def _handle_connect(self):
|
||||
gcode = self.printer.lookup_object('gcode')
|
||||
gcode.register_output_handler(self._process_gcode_response)
|
||||
|
||||
def _notify_shutdown(self):
|
||||
self.call_remote_method("set_klippy_shutdown")
|
||||
|
||||
def _process_gcode_response(self, gc_response):
|
||||
self.call_remote_method(
|
||||
"process_gcode_response", response=gc_response)
|
||||
|
||||
def register_endpoint(self, path, callback):
|
||||
if path in self._endpoints:
|
||||
raise WebRequestError("Path already registered to an endpoint")
|
||||
|
@ -318,6 +315,46 @@ class WebHooks:
|
|||
"action_call_remote_method": self._action_call_remote_method
|
||||
}
|
||||
|
||||
class GCodeHelper:
|
||||
def __init__(self, printer):
|
||||
self.printer = printer
|
||||
self.gcode = printer.lookup_object("gcode")
|
||||
# Output subscription tracking
|
||||
self.is_output_registered = False
|
||||
self.clients = {}
|
||||
# Register webhooks
|
||||
wh = printer.lookup_object('webhooks')
|
||||
wh.register_endpoint("gcode/help", self._handle_help)
|
||||
wh.register_endpoint("gcode/script", self._handle_script)
|
||||
wh.register_endpoint("gcode/restart", self._handle_restart)
|
||||
wh.register_endpoint("gcode/firmware_restart",
|
||||
self._handle_firmware_restart)
|
||||
wh.register_endpoint("gcode/subscribe_output",
|
||||
self._handle_subscribe_output)
|
||||
def _handle_help(self, web_request):
|
||||
web_request.send(self.gcode.get_command_help())
|
||||
def _handle_script(self, web_request):
|
||||
self.gcode.run_script(web_request.get('script'))
|
||||
def _handle_restart(self, web_request):
|
||||
self.gcode.run_script('restart')
|
||||
def _handle_firmware_restart(self, web_request):
|
||||
self.gcode.run_script('firmware_restart')
|
||||
def _output_callback(self, msg):
|
||||
for cconn, template in list(self.clients.items()):
|
||||
if cconn.is_closed():
|
||||
del self.clients[cconn]
|
||||
continue
|
||||
tmp = dict(template)
|
||||
tmp['params'] = {'response': msg}
|
||||
cconn.send(tmp)
|
||||
def _handle_subscribe_output(self, web_request):
|
||||
cconn = web_request.get_client_connection()
|
||||
template = web_request.get('response_template', {})
|
||||
self.clients[cconn] = template
|
||||
if not self.is_output_registered:
|
||||
self.gcode.register_output_handler(self._output_callback)
|
||||
self.is_output_registered = True
|
||||
|
||||
SUBSCRIPTION_REFRESH_TIME = .25
|
||||
|
||||
class StatusHandler:
|
||||
|
@ -443,4 +480,5 @@ class StatusHandler:
|
|||
|
||||
def add_early_printer_objects(printer):
|
||||
printer.add_object('webhooks', WebHooks(printer))
|
||||
GCodeHelper(printer)
|
||||
StatusHandler(printer)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue