From d5810a530f72be93678c27f2c3007ce728f871bf Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Mon, 19 Jun 2023 23:24:10 -0600
Subject: [PATCH 1/3] Cache API clients to reduce 500 risk(s)

---
 projects/tentacles/src/python/tentacles/workers.py | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/projects/tentacles/src/python/tentacles/workers.py b/projects/tentacles/src/python/tentacles/workers.py
index 03cd5e9..ec0024d 100644
--- a/projects/tentacles/src/python/tentacles/workers.py
+++ b/projects/tentacles/src/python/tentacles/workers.py
@@ -8,6 +8,7 @@ Mostly related to monitoring and managing Printer state.
 """
 
 from contextlib import closing
+from functools import cache
 import logging
 from pathlib import Path
 from pprint import pformat
@@ -49,6 +50,11 @@ class OctoRest(_OR):
                 raise e
 
 
+@cache
+def get_client(url, key):
+    return OctoRest(url=url, apikey=key)
+
+
 log = logging.getLogger(__name__)
 
 
@@ -65,7 +71,7 @@ def poll_printers(app: App, db: Db) -> None:
 
         printer_job = {}
         try:
-            client = OctoRest(url=printer.url, apikey=printer.api_key)
+            client = get_client(printer.url, printer.api_key)
             printer_job: dict = client.job_info()
             try:
                 printer_state: dict = client.printer().get("state").get("flags", {})
@@ -136,7 +142,7 @@ def push_jobs(app: App, db: Db) -> None:
             db.delete_job(job.user_id, job.id)
 
         try:
-            client = OctoRest(url=printer.url, apikey=printer.api_key)
+            client = get_client(printer.url, printer.api_key)
             printer_job = client.job_info()
             try:
                 printer_state = client.printer().get("state").get("flags", {})
@@ -182,7 +188,7 @@ def revoke_jobs(app: App, db: Db) -> None:
 
             try:
                 log.info(f"Cancelling running job {job.id}")
-                client = OctoRest(url=printer.url, apikey=printer.api_key)
+                client = get_client(printer.url, printer.api_key)
                 try:
                     client.cancel()
                 except HTTPError as e:
@@ -211,7 +217,7 @@ def pull_jobs(app: App, db: Db) -> None:
     for job in db.list_running_jobs():
         printer = db.fetch_printer(pid=job.printer_id)
         try:
-            client = OctoRest(url=printer.url, apikey=printer.api_key)
+            client = get_client(printer.url, printer.api_key)
             job_state = client.job_info()
             try:
                 printer_state = client.printer().get("state").get("flags", {})

From ae1d00b13f3551dfb70f429271f55c971f4859cd Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Mon, 19 Jun 2023 23:25:03 -0600
Subject: [PATCH 2/3] Create an 'occupied' state for unready beds

---
 projects/tentacles/src/python/tentacles/schema.sql | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/projects/tentacles/src/python/tentacles/schema.sql b/projects/tentacles/src/python/tentacles/schema.sql
index 1e36258..4c1f3d8 100644
--- a/projects/tentacles/src/python/tentacles/schema.sql
+++ b/projects/tentacles/src/python/tentacles/schema.sql
@@ -157,6 +157,10 @@ CREATE TABLE IF NOT EXISTS email_spool (
  , FOREIGN KEY(user_id) REFERENCES users(id)
 );
 
+-- name: migration-0002-create-occupied-state
+-- Create a state representing that the printer needs to be unloaded after a print
+INSERT OR IGNORE INTO printer_statuses (id, name) VALUES (5, 'occupied');
+
 ----------------------------------------------------------------------------------------------------
 -- Users
 ----------------------------------------------------------------------------------------------------

From 730a6a3950b751cb9177c6cabce0e5541de0fa91 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Mon, 19 Jun 2023 23:24:39 -0600
Subject: [PATCH 3/3] Use the bedready plugin to check if the bed is clear or
 occupied

---
 .../tentacles/src/python/tentacles/workers.py | 23 ++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/projects/tentacles/src/python/tentacles/workers.py b/projects/tentacles/src/python/tentacles/workers.py
index ec0024d..90f599f 100644
--- a/projects/tentacles/src/python/tentacles/workers.py
+++ b/projects/tentacles/src/python/tentacles/workers.py
@@ -69,6 +69,24 @@ def poll_printers(app: App, db: Db) -> None:
                 log.info(f"Printer {printer.id} {printer.status} -> {status}")
             db.update_printer_status(pid=printer.id, status=status)
 
+        def _bed_clear():
+            if not (
+                snapshots := client._post(
+                    "/api/plugin/bedready", json={"command": "list_snapshots"}
+                )
+            ):
+                return True  # Assume the bed is ready
+
+            status = client._post(
+                "/api/plugin/bedready",
+                json={
+                    "command": "check_bed",
+                    "similarity": 0.97,
+                    "reference": snapshots[0],
+                },
+            )
+            return status.get("bed_clear", True)
+
         printer_job = {}
         try:
             client = get_client(printer.url, printer.api_key)
@@ -98,7 +116,10 @@ def poll_printers(app: App, db: Db) -> None:
                 _set_status("connecting")
 
             elif printer_state.get("ready"):
-                _set_status("idle")
+                if _bed_clear():
+                    _set_status("idle")
+                else:
+                    _set_status("occupied")
 
             else:
                 raise Exception(