Color and continuous printing

This commit is contained in:
Reid D McKenzie 2025-02-07 23:59:32 -07:00
parent 35ae07d7e3
commit 8712ddc377
6 changed files with 81 additions and 59 deletions

View file

@ -119,6 +119,7 @@ def create_file(location: Optional[str] = None):
fid=row.id,
cid=None,
pid=None,
cont=False, # FIXME: How to decide this?
)
return {"status": "ok"}, 202

View file

@ -39,17 +39,20 @@ def manipulate_jobs():
fid=int(request.form.get("file_id")),
cid=maybe(int, request.form.get("color_id")),
pid=maybe(int, request.form.get("printer_id")),
cont=request.form.get("continuous") == "on",
)
flash("Job created!", category="info")
case "duplicate":
if job := ctx.db.fetch_job(
uid=ctx.uid, jid=int(request.form.get("job_id"))
uid=ctx.uid,
jid=int(request.form.get("job_id")),
):
ctx.db.create_job(
uid=ctx.uid,
fid=job.file_id,
cid=job.color_id,
cont=job.continuous,
# FIXME: Need to dissociate job copies from the original mapped printer. Can't tell the difference
# between the requested printer in the original job and the mapped printer from a scheduler run.
pid=None,

View file

@ -27,10 +27,13 @@ CREATE TABLE IF NOT EXISTS jobs (
);
-- name: migration-0001-jobs-add-print-time#
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS time_left INTEGER DEFAULT (0);
ALTER TABLE jobs ADD COLUMN time_left INTEGER DEFAULT (0);
-- name: migration-0002-jobs-add-print-color#
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS color_id INTEGER DEFAULT (NULL);
ALTER TABLE jobs ADD COLUMN color_id INTEGER DEFAULT (NULL);
-- name: migration-0003-jobs-add-continuous#
ALTER TABLE jobs ADD COLUMN continuous BOOLEAN DEFAULT (FALSE);
-- name: create-job^
INSERT INTO jobs (
@ -38,12 +41,14 @@ INSERT INTO jobs (
, file_id
, color_id
, printer_id
, continuous
)
VALUES (
:uid
, :fid
, :cid
, :pid
, :cont
)
RETURNING
*
@ -78,36 +83,46 @@ WHERE
-- name: list-job-queue
SELECT
j.id as id
, j.file_id
, coalesce(j.color_id, fa.color_id) as color_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
, (SELECT name FROM filament WHERE id = fa.filament_id) AS filament_name
, (SELECT name AS name FROM filament_color WHERE id = coalesce(j.color_id, fa.color_id)) AS color_name
, (SELECT name FROM job_statuses WHERE id = j.status_id) AS status
, j.started_at
, j.time_left
, j.cancelled_at
, j.finished_at
, j.user_id
, j.printer_id
FROM jobs j
INNER JOIN files f
ON j.file_id = f.id
LEFT JOIN file_analysis fa
ON fa.file_id = f.id
WHERE
finished_at IS NULL
AND cancelled_at IS NULL
AND (:uid IS NULL OR j.user_id = :uid)
AND f.id IS NOT NULL
*
FROM (
SELECT
j.id as id
, j.file_id
, coalesce(j.color_id, fa.color_id) as color_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
, (SELECT name FROM filament WHERE id = fa.filament_id) AS filament_name
, (SELECT name AS name FROM filament_color WHERE id = coalesce(j.color_id, fa.color_id)) AS color_name
, j.status_id
, (SELECT name FROM job_statuses WHERE id = j.status_id) AS status
, j.started_at
, j.time_left
, j.cancelled_at
, j.finished_at
, j.user_id
, j.printer_id
, j.continuous
FROM jobs j
INNER JOIN files f
ON j.file_id = f.id
LEFT JOIN file_analysis fa
ON fa.file_id = f.id
WHERE
finished_at IS NULL
AND cancelled_at IS NULL
AND (:uid IS NULL OR j.user_id = :uid)
AND f.id IS NOT NULL
)
ORDER BY
status_id DESC
, continuous DESC
, id
;
-- name: poll-job-queue^

View file

@ -9,32 +9,14 @@
<label for="filename">File</label>
<span name="filename">{{ctx.db.fetch_file(ctx.uid, job.file_id).filename or "it's a secret"}}</span>
</div>
{% if job.printer_id %}
<div class="job-printer u-flex u-flex-break">
<label for="printer">Printer</label>
<span name="printer">{{ ctx.db.fetch_printer(job.printer_id).name }}</span>
</div>
{% endif %}
{% if job.started_at %}
<div class="job-runtime u-flex u-flex-break">
<label for="runtime">Runtime</label>
<span name="Runtime">{{ (datetime.utcnow() - datetime.fromisoformat(job.started_at)) }}</span>
</div>
{% endif %}
{% if job.time_left > 0 %}
<div class="job-remaining-time u-flex u-flex-break">
<label for="remaining-time">Remaining time</label>
<span name="remaining-time">{{ timedelta(seconds=job.time_left) }}</span>
</div>
{% endif %}
<div class="job-constraint u-flex u-flex-break">
<div class="job-constraint u-flex">
<label>Material</label>
{{ job.color_name }}
{{ job.filament_name }}
</div>
<div class="job-constraint u-flex u-flex-break">
<label>Limits</label>
{{ job.max_x }}mm x{{ job.max_y }}mm x{{ job.max_z }}mm, bed {{ job.max_bed }}c, end {{ job.max_end }}c, nozzle {{ "%.2f"|format(job.nozzle_diameter) }}mm
<div class="job-cont u-flex">
<label>Continuous</label>
{% if job.continuous == 1 %}True{% else %}False{% endif %}
</div>
{% if job.user_id != ctx.uid %}
<div class="job-user u-flex">
@ -42,6 +24,24 @@
{{ ctx.db.fetch_user(uid=job.user_id).name }}
</div>
{% endif %}
{% if job.printer_id %}
<div class="job-printer u-flex">
<label for="printer">Printer</label>
<span name="printer">{{ ctx.db.fetch_printer(job.printer_id).name }}</span>
</div>
{% endif %}
{% if job.started_at %}
<div class="job-runtime u-flex">
<label for="runtime">Runtime</label>
<span name="Runtime">{{ (datetime.utcnow() - datetime.fromisoformat(job.started_at)) }}</span>
</div>
{% endif %}
{% if job.time_left > 0 %}
<div class="job-remaining-time u-flex">
<label for="remaining-time">Remaining time</label>
<span name="remaining-time">{{ timedelta(seconds=job.time_left) }}</span>
</div>
{% endif %}
</div>
<div class="two columns u-mv-auto">
<div class="job-status u-flex">

View file

@ -1,7 +1,7 @@
{# #################################################################################################### #}
{# Job CRUD #}
{% macro start_job(file) %}
<form class="inline" method="post" action="/jobs">
<form class="start-menu inline u-flex" method="post" action="/jobs">
<input type="hidden" name="action" value="enqueue" />
<input type="hidden" name="file_id" value="{{ file.id }}" />
<select name="color_id">
@ -9,7 +9,11 @@
<option value="{{c.id}}" {% if file.color_id == c.id %}selected{%endif%}>{{c.name}}</option>
{%- endfor %}
</select>
<input id="submit" type="image" src="/static/print.svg" height="24" width="24" />
<div class="u-flex u-ml-auto u-mv-auto u-flex u-ml-1">
<label class="u-flex u-mv-auto" for="continuous">Cont.</label>
<input class="u-flex u-mv-auto" type="checkbox" name="continuous" false>
</div>
<input id="submit" type="image" src="/static/print.svg" height="24" width="24" />
</form>
{% endmacro %}

View file

@ -270,8 +270,7 @@ def pull_jobs(app: App, db: Db) -> None:
if runtime >= timedelta(seconds=15): # 3 polling cycles
log.info(f"Job {job.id} has succeeded")
# Attempt to automatically clear the bed
if False:
if job.continuous:
log.info(f"Attempting to clear bed of {printer.id} ({printer.url})")
client.gcode(
"""\