More limits refinements

This commit is contained in:
Reid 'arrdem' McKenzie 2023-07-08 17:35:17 -06:00
parent 4fa627919b
commit a281f24689
7 changed files with 67 additions and 17 deletions

View file

@ -37,6 +37,7 @@ class GcodeAnalysis:
max_bed: int max_bed: int
max_end: int max_end: int
filament: str filament: str
nozzle: int
def parse_point(point: str) -> Tuple[int, int]: def parse_point(point: str) -> Tuple[int, int]:
@ -88,6 +89,11 @@ def analyze_gcode_str(text: str) -> Optional[GcodeAnalysis]:
else: else:
return None return None
if "nozzle_diameter" in opts:
kwargs["nozzle"] = float(opts["nozzle_diameter"])
else:
return None
return GcodeAnalysis(**kwargs) return GcodeAnalysis(**kwargs)

View file

@ -16,6 +16,7 @@ CREATE TABLE IF NOT EXISTS file_analysis (
, max_z INTEGER , max_z INTEGER
, max_end INTEGER , max_end INTEGER
, max_bed INTEGER , max_bed INTEGER
, nozzle_diameter FLOAT
, filament_id INTEGER REFERENCES filament(id) , filament_id INTEGER REFERENCES filament(id)
, file_id INTEGER REFERENCES file(id) , file_id INTEGER REFERENCES file(id)
); );
@ -60,11 +61,12 @@ WHERE
-- name: create-analysis^ -- name: create-analysis^
INSERT INTO file_analysis ( INSERT INTO file_analysis (
, max_x max_x
, max_y , max_y
, max_z , max_z
, max_end , max_end
, max_bed , max_bed
, nozzle_diameter
, filament_id , filament_id
, file_id , file_id
) )
@ -74,6 +76,7 @@ VALUES (
, :max_z , :max_z
, :max_end , :max_end
, :max_bed , :max_bed
, :nozzle
, :filament_id , :filament_id
, :file_id , :file_id
) )
@ -84,7 +87,9 @@ RETURNING
-- name: list-unanalyzed-files -- name: list-unanalyzed-files
SELECT SELECT
f.id f.id
, f.path
, f.filename , f.filename
, f.user_id
FROM files f FROM files f
LEFT JOIN file_analysis fa LEFT JOIN file_analysis fa
ON f.id = fa.file_id ON f.id = fa.file_id

View file

@ -68,17 +68,25 @@ WHERE
-- name: list-job-queue -- name: list-job-queue
SELECT 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 FROM jobs j
INNER JOIN files f INNER JOIN files f
ON j.file_id = f.id ON j.file_id = f.id
INNER JOIN file_analysis fa LEFT JOIN file_analysis fa
ON fa.file_id = f.id ON fa.file_id = f.id
WHERE WHERE
finished_at IS NULL finished_at IS NULL
AND (:uid IS NULL OR j.user_id = :uid) AND (:uid IS NULL OR j.user_id = :uid)
AND f.id IS NOT NULL AND f.id IS NOT NULL
AND fa.id IS NOT NULL
; ;
-- name: poll-job-queue^ -- name: poll-job-queue^

View file

@ -76,7 +76,7 @@ ALTER TABLE printers ADD filament_id INTEGER REFERENCES filament(id) DEFAULT 1;
ALTER TABLE printers ADD enabled BOOLEAN DEFAULT TRUE; ALTER TABLE printers ADD enabled BOOLEAN DEFAULT TRUE;
-- name: migration-0005-create-printer-nozzle# -- 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^ -- name: try-create-printer^
INSERT INTO printers ( INSERT INTO printers (
@ -116,8 +116,19 @@ SELECT
, p.api_key , p.api_key
, p.last_poll_date , p.last_poll_date
, s.name as status , 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 FROM printers p
INNER JOIN printer_statuses s ON p.status_id = s.id 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 -- name: list-idle-printers
@ -126,9 +137,8 @@ SELECT
, c.limit_x , c.limit_x
, c.limit_y , c.limit_y
, c.limit_z , c.limit_z
, c.limit_hotend
, c.limit_bed , c.limit_bed
, c.limit_tools , c.limit_hotend
, p.nozzle_diameter , p.nozzle_diameter
FROM printers p FROM printers p
LEFT JOIN (SELECT id, printer_id FROM jobs WHERE finished_at IS NULL) j LEFT JOIN (SELECT id, printer_id FROM jobs WHERE finished_at IS NULL) j

View file

@ -6,6 +6,10 @@
<div class="u-flex1 webcam" style="max-width: calc(100% / {{printers|length}})"> <div class="u-flex1 webcam" style="max-width: calc(100% / {{printers|length}})">
<label>{{ printer.name }}</label> <label>{{ printer.name }}</label>
<img id="printer_{{printer.id}}_stream" src="{{ printer.stream_url }}" style="max-width: 100%;" /> <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> </div>
{% endfor %} {% endfor %}
</div> </div>

View file

@ -147,10 +147,20 @@ def poll_printers(app: App, db: Db) -> None:
def assign_jobs(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.""" """Assign jobs to printers. Uploading files and job state management is handled separately."""
for printer in db.list_idle_printers(): for job in db.list_job_queue(uid=None):
if job := db.poll_job_queue(): for printer in db.list_idle_printers():
db.assign_job(jid=job.id, pid=printer.id) if (
log.info(f"Mapped job {job.id} to printer {printer.id}") 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: 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): def analyze_files(app: App, db: Db):
for unanalyzed in db.list_unanalyzed_files(): 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( db.create_analysis(
file_id=unanalyzed.id, file_id=unanalyzed.id,
max_x=record.max_x, max_x=record.max_x,
@ -308,14 +324,14 @@ def analyze_files(app: App, db: Db):
def debug_queue(app: App, db: Db): def debug_queue(app: App, db: Db):
output = ["---"] output = ["---"]
for job in db.list_running_jobs(): for job in db.list_job_queue(uid=None):
output.append(repr(job)) output.append("Job " + repr(job))
for printer in db.list_idle_printers(): for printer in db.list_idle_printers():
output.append(repr(printer)) output.append("Printer " + repr(printer))
for unanalyzed in db.list_unanalyzed_files(): for unanalyzed in db.list_unanalyzed_files():
output.append(repr(unanalyzed)) output.append("Unanalyzed file " + repr(unanalyzed))
print("\n".join(output)) print("\n".join(output))

View file

@ -46,9 +46,10 @@ more garbage
; first_layer_bed_temperature = 100 ; first_layer_bed_temperature = 100
; first_layer_temperature = 195 ; first_layer_temperature = 195
; filament_type = PETG ; filament_type = PETG
; nozzle_diameter = 1.0
; prusaslicer_config = end ; prusaslicer_config = end
""" """
) )
== GcodeAnalysis(100, 100, 100, 100, 195, "PETG") == GcodeAnalysis(100, 100, 100, 100, 195, "PETG", 1.0)
) )