diff --git a/projects/tentacles/src/python/gcode.py b/projects/tentacles/src/python/gcode.py
index c2761a4..4131aef 100644
--- a/projects/tentacles/src/python/gcode.py
+++ b/projects/tentacles/src/python/gcode.py
@@ -37,6 +37,7 @@ class GcodeAnalysis:
     max_bed: int
     max_end: int
     filament: str
+    nozzle: int
 
 
 def parse_point(point: str) -> Tuple[int, int]:
@@ -88,6 +89,11 @@ def analyze_gcode_str(text: str) -> Optional[GcodeAnalysis]:
     else:
         return None
 
+    if "nozzle_diameter" in opts:
+        kwargs["nozzle"] = float(opts["nozzle_diameter"])
+    else:
+        return None
+
     return GcodeAnalysis(**kwargs)
 
 
diff --git a/projects/tentacles/src/python/tentacles/sql/files.sql b/projects/tentacles/src/python/tentacles/sql/files.sql
index 389d096..9a53828 100644
--- a/projects/tentacles/src/python/tentacles/sql/files.sql
+++ b/projects/tentacles/src/python/tentacles/sql/files.sql
@@ -16,6 +16,7 @@ CREATE TABLE IF NOT EXISTS file_analysis (
  , max_z INTEGER
  , max_end INTEGER
  , max_bed INTEGER
+ , nozzle_diameter FLOAT
  , filament_id INTEGER REFERENCES filament(id)
  , file_id INTEGER REFERENCES file(id)
 );
@@ -60,11 +61,12 @@ WHERE
 
 -- name: create-analysis^
 INSERT INTO file_analysis (
- , max_x
+   max_x
  , max_y
  , max_z
  , max_end
  , max_bed
+ , nozzle_diameter
  , filament_id
  , file_id
 )
@@ -74,6 +76,7 @@ VALUES (
  , :max_z
  , :max_end
  , :max_bed
+ , :nozzle
  , :filament_id
  , :file_id
 )
@@ -84,7 +87,9 @@ RETURNING
 -- name: list-unanalyzed-files
 SELECT
    f.id
+ , f.path
  , f.filename
+ , f.user_id
 FROM files f
 LEFT JOIN file_analysis fa
    ON f.id = fa.file_id
diff --git a/projects/tentacles/src/python/tentacles/sql/jobs.sql b/projects/tentacles/src/python/tentacles/sql/jobs.sql
index 3d8ded8..7c9ef2b 100644
--- a/projects/tentacles/src/python/tentacles/sql/jobs.sql
+++ b/projects/tentacles/src/python/tentacles/sql/jobs.sql
@@ -68,17 +68,25 @@ WHERE
 
 -- name: list-job-queue
 SELECT
-   *
+   j.id as id
+ , j.file_id
+ , fa.id as analysis_id
+ , fa.max_x
+ , fa.max_y
+ , fa.max_z
+ , fa.max_bed
+ , fa.max_end
+ , fa.nozzle_diameter
+ , fa.filament_id
 FROM jobs j
 INNER JOIN files f
   ON j.file_id = f.id
-INNER JOIN file_analysis fa
+LEFT JOIN file_analysis fa
   ON fa.file_id = f.id
 WHERE
    finished_at IS NULL
    AND (:uid IS NULL OR j.user_id = :uid)
    AND f.id IS NOT NULL
-   AND fa.id IS NOT NULL
 ;
 
 -- name: poll-job-queue^
diff --git a/projects/tentacles/src/python/tentacles/sql/printers.sql b/projects/tentacles/src/python/tentacles/sql/printers.sql
index 16eb881..3901f46 100644
--- a/projects/tentacles/src/python/tentacles/sql/printers.sql
+++ b/projects/tentacles/src/python/tentacles/sql/printers.sql
@@ -76,7 +76,7 @@ ALTER TABLE printers ADD filament_id INTEGER REFERENCES filament(id) DEFAULT 1;
 ALTER TABLE printers ADD enabled BOOLEAN DEFAULT TRUE;
 
 -- name: migration-0005-create-printer-nozzle#
-ALTER TABLE printers ADD nozzle_diameter INTEGER default 4;
+ALTER TABLE printers ADD nozzle_diameter FLOAT DEFAULT 0.4;
 
 -- name: try-create-printer^
 INSERT INTO printers (
@@ -116,8 +116,19 @@ SELECT
  , p.api_key
  , p.last_poll_date
  , s.name as status
+ , p.enabled
+ , f.name as filament_name
+ , c.name as machine_name
+ , c.limit_x
+ , c.limit_y
+ , c.limit_z
+ , c.limit_bed
+ , c.limit_hotend
+ , p.nozzle_diameter
 FROM printers p
 INNER JOIN printer_statuses s ON p.status_id = s.id
+INNER JOIN filament f on p.filament_id = f.id
+INNER JOIN printer_chassis c on p.chassis_id = c.id
 ;
 
 -- name: list-idle-printers
@@ -126,9 +137,8 @@ SELECT
  , c.limit_x
  , c.limit_y
  , c.limit_z
- , c.limit_hotend
  , c.limit_bed
- , c.limit_tools
+ , c.limit_hotend
  , p.nozzle_diameter
 FROM printers p
 LEFT JOIN (SELECT id, printer_id FROM jobs WHERE finished_at IS NULL) j
diff --git a/projects/tentacles/src/python/tentacles/templates/streams.html.j2 b/projects/tentacles/src/python/tentacles/templates/streams.html.j2
index 16d8713..450ca89 100644
--- a/projects/tentacles/src/python/tentacles/templates/streams.html.j2
+++ b/projects/tentacles/src/python/tentacles/templates/streams.html.j2
@@ -6,6 +6,10 @@
     <div class="u-flex1 webcam" style="max-width: calc(100% / {{printers|length}})">
       <label>{{ printer.name }}</label>
       <img id="printer_{{printer.id}}_stream" src="{{ printer.stream_url }}" style="max-width: 100%;" />
+      <span><label>Status</label>{{printer.status}}, {% if printer.enabled %}accepting jobs{%else%}not scheduling{%endif%}</span>
+      <span><label>Loaded material</label>{{printer.filament_name}}</span>
+      <span><label>Machine</label>{{printer.machine_name}}</span>
+      <span><label>Limits</label>{{printer.limit_x}}mm x{{printer.limit_y}}mm x{{printer.limit_z}}mm, bed {{printer.limit_bed}}c, end {{printer.limit_hotend}}c</span>
     </div>
   {% endfor %}
 </div>
diff --git a/projects/tentacles/src/python/tentacles/workers.py b/projects/tentacles/src/python/tentacles/workers.py
index c366159..dff20cb 100644
--- a/projects/tentacles/src/python/tentacles/workers.py
+++ b/projects/tentacles/src/python/tentacles/workers.py
@@ -147,10 +147,20 @@ def poll_printers(app: App, db: Db) -> None:
 def assign_jobs(app: App, db: Db) -> None:
     """Assign jobs to printers. Uploading files and job state management is handled separately."""
 
-    for printer in db.list_idle_printers():
-        if job := db.poll_job_queue():
-            db.assign_job(jid=job.id, pid=printer.id)
-            log.info(f"Mapped job {job.id} to printer {printer.id}")
+    for job in db.list_job_queue(uid=None):
+        for printer in db.list_idle_printers():
+            if (
+                printer.limit_x >= job.max_x
+                and printer.limit_y >= job.max_y
+                and printer.limit_z >= job.max_z
+                and printer.limit_hotend >= job.max_end
+                and printer.limit_bed >= job.max_bed
+                and printer.nozzle_diameter == job.nozzle_diameter
+                and printer.filament_id == job.filament_id
+            ):
+                db.assign_job(jid=job.id, pid=printer.id)
+                log.info(f"Mapped job {job.id} to printer {printer.id}")
+                break
 
 
 def push_jobs(app: App, db: Db) -> None:
@@ -293,7 +303,13 @@ def send_emails(app, db: Db):
 
 def analyze_files(app: App, db: Db):
     for unanalyzed in db.list_unanalyzed_files():
-        record = analyze_gcode_file(Path(unanalyzed.filename))
+        record = analyze_gcode_file(Path(unanalyzed.path))
+        if not record:
+            log.error(
+                f"Unable to analyze {unanalyzed.path} ({unanalyzed.filename} owned by {unanalyzed.user_id})!"
+            )
+            continue
+
         db.create_analysis(
             file_id=unanalyzed.id,
             max_x=record.max_x,
@@ -308,14 +324,14 @@ def analyze_files(app: App, db: Db):
 def debug_queue(app: App, db: Db):
     output = ["---"]
 
-    for job in db.list_running_jobs():
-        output.append(repr(job))
+    for job in db.list_job_queue(uid=None):
+        output.append("Job " + repr(job))
 
     for printer in db.list_idle_printers():
-        output.append(repr(printer))
+        output.append("Printer " + repr(printer))
 
     for unanalyzed in db.list_unanalyzed_files():
-        output.append(repr(unanalyzed))
+        output.append("Unanalyzed file " + repr(unanalyzed))
 
     print("\n".join(output))
 
diff --git a/projects/tentacles/test/python/test_gcode.py b/projects/tentacles/test/python/test_gcode.py
index 12ceb7c..5f1164a 100644
--- a/projects/tentacles/test/python/test_gcode.py
+++ b/projects/tentacles/test/python/test_gcode.py
@@ -46,9 +46,10 @@ more garbage
 ; first_layer_bed_temperature = 100
 ; first_layer_temperature = 195
 ; filament_type = PETG
+; nozzle_diameter = 1.0
 ; prusaslicer_config = end
 
 """
         )
-        == GcodeAnalysis(100, 100, 100, 100, 195, "PETG")
+        == GcodeAnalysis(100, 100, 100, 100, 195, "PETG", 1.0)
     )