Bring bed leveling inboard
This commit is contained in:
parent
81e60284c0
commit
5dd0694a98
8 changed files with 76 additions and 15 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
"""The core app entrypoint."""
|
"""The core app entrypoint."""
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import tomllib
|
import tomllib
|
||||||
|
@ -46,6 +46,7 @@ def create_j2_request_global(app):
|
||||||
app.jinja_env.globals["ctx"] = ctx
|
app.jinja_env.globals["ctx"] = ctx
|
||||||
app.jinja_env.globals["request"] = request
|
app.jinja_env.globals["request"] = request
|
||||||
app.jinja_env.globals["datetime"] = datetime
|
app.jinja_env.globals["datetime"] = datetime
|
||||||
|
app.jinja_env.globals["timedelta"] = timedelta
|
||||||
|
|
||||||
|
|
||||||
def user_session():
|
def user_session():
|
||||||
|
|
|
@ -21,7 +21,7 @@ from aiosql.query_loader import QueryLoader
|
||||||
|
|
||||||
_sqlite = get_adapter("sqlite3")
|
_sqlite = get_adapter("sqlite3")
|
||||||
_loader = QueryLoader(_sqlite, None)
|
_loader = QueryLoader(_sqlite, None)
|
||||||
_queries = Queries(_sqlite)
|
_queries = Queries(_sqlite, kwargs_only=False)
|
||||||
for f in files("tentacles.sql").iterdir():
|
for f in files("tentacles.sql").iterdir():
|
||||||
if f.is_file() and f.name.endswith(".sql"):
|
if f.is_file() and f.name.endswith(".sql"):
|
||||||
print("Loading", f)
|
print("Loading", f)
|
||||||
|
|
|
@ -26,6 +26,9 @@ CREATE TABLE IF NOT EXISTS jobs (
|
||||||
, FOREIGN KEY(printer_id) REFERENCES printer(id)
|
, FOREIGN KEY(printer_id) REFERENCES printer(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- name: migration-0001-jobs-add-print-time#
|
||||||
|
ALTER TABLE jobs ADD COLUMN time_left INTEGER DEFAULT (0);
|
||||||
|
|
||||||
-- name: create-job^
|
-- name: create-job^
|
||||||
INSERT INTO jobs (
|
INSERT INTO jobs (
|
||||||
user_id
|
user_id
|
||||||
|
@ -81,6 +84,7 @@ SELECT
|
||||||
, (SELECT name FROM filament WHERE id = fa.filament_id) AS filament_name
|
, (SELECT name FROM filament WHERE id = fa.filament_id) AS filament_name
|
||||||
, (SELECT name FROM job_statuses WHERE id = j.status_id) AS status
|
, (SELECT name FROM job_statuses WHERE id = j.status_id) AS status
|
||||||
, j.started_at
|
, j.started_at
|
||||||
|
, j.time_left
|
||||||
, j.cancelled_at
|
, j.cancelled_at
|
||||||
, j.finished_at
|
, j.finished_at
|
||||||
, j.user_id
|
, j.user_id
|
||||||
|
@ -220,3 +224,10 @@ UPDATE jobs
|
||||||
WHERE
|
WHERE
|
||||||
id = :jid
|
id = :jid
|
||||||
;
|
;
|
||||||
|
|
||||||
|
-- name: update-job-time-left!
|
||||||
|
UPDATE jobs
|
||||||
|
SET time_left = :time_left
|
||||||
|
WHERE
|
||||||
|
id = :jid
|
||||||
|
;
|
||||||
|
|
|
@ -78,6 +78,9 @@ 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 FLOAT DEFAULT 0.4;
|
ALTER TABLE printers ADD nozzle_diameter FLOAT DEFAULT 0.4;
|
||||||
|
|
||||||
|
-- name: migration-0006-create-printer-level-date#
|
||||||
|
ALTER TABLE printers ADD last_level_date TEXT DEFAULT NULL;
|
||||||
|
|
||||||
-- name: try-create-printer^
|
-- name: try-create-printer^
|
||||||
INSERT INTO printers (
|
INSERT INTO printers (
|
||||||
name
|
name
|
||||||
|
@ -98,6 +101,7 @@ SELECT
|
||||||
, p.stream_url
|
, p.stream_url
|
||||||
, p.api_key
|
, p.api_key
|
||||||
, p.last_poll_date
|
, p.last_poll_date
|
||||||
|
, p.last_level_date
|
||||||
, p.filament_id
|
, p.filament_id
|
||||||
, p.chassis_id
|
, p.chassis_id
|
||||||
, p.enabled
|
, p.enabled
|
||||||
|
@ -116,6 +120,7 @@ SELECT
|
||||||
, p.stream_url
|
, p.stream_url
|
||||||
, p.api_key
|
, p.api_key
|
||||||
, p.last_poll_date
|
, p.last_poll_date
|
||||||
|
, p.last_level_date
|
||||||
, s.name as status
|
, s.name as status
|
||||||
, p.enabled
|
, p.enabled
|
||||||
, f.name as filament_name
|
, f.name as filament_name
|
||||||
|
@ -166,6 +171,14 @@ WHERE
|
||||||
id = :pid
|
id = :pid
|
||||||
;
|
;
|
||||||
|
|
||||||
|
-- name: update-printer-level-date!
|
||||||
|
UPDATE printers
|
||||||
|
SET
|
||||||
|
, last_level_date = datetime('now')
|
||||||
|
WHERE
|
||||||
|
id = :pid
|
||||||
|
;
|
||||||
|
|
||||||
-- name: edit-printer!
|
-- name: edit-printer!
|
||||||
UPDATE printers
|
UPDATE printers
|
||||||
SET
|
SET
|
||||||
|
|
|
@ -22,6 +22,14 @@
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.div .job {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.div .job:not(:last-child) {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
.file .details,
|
.file .details,
|
||||||
.printer .details,
|
.printer .details,
|
||||||
.key .details,
|
.key .details,
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="controls u-flex u-ml-auto u-mv-auto">
|
<div class="controls u-flex u-ml-auto u-mv-auto">
|
||||||
{{ macros.start_job(file.id) }}
|
|
||||||
{{ macros.download_file(file.id) }}
|
{{ macros.download_file(file.id) }}
|
||||||
|
{{ macros.start_job(file.id) }}
|
||||||
{{ macros.delete_file(file.id) }}
|
{{ macros.delete_file(file.id) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,18 +10,24 @@
|
||||||
<span name="filename">{{ctx.db.fetch_file(ctx.uid, job.file_id).filename or "it's a secret"}}</span>
|
<span name="filename">{{ctx.db.fetch_file(ctx.uid, job.file_id).filename or "it's a secret"}}</span>
|
||||||
</div>
|
</div>
|
||||||
{% if job.printer_id %}
|
{% if job.printer_id %}
|
||||||
<div class="job-printer u-flex">
|
<div class="job-printer u-flex u-flex-break">
|
||||||
<label for="printer">Printer</label>
|
<label for="printer">Printer</label>
|
||||||
<span name="printer">{{ ctx.db.fetch_printer(job.printer_id).name }}</span>
|
<span name="printer">{{ ctx.db.fetch_printer(job.printer_id).name }}</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if job.started_at %}
|
{% if job.started_at %}
|
||||||
<div class="job-runtime u-flex">
|
<div class="job-runtime u-flex u-flex-break">
|
||||||
<label for="runtime">Runtime</label>
|
<label for="runtime">Runtime</label>
|
||||||
<span name="Runtime">{{ (datetime.utcnow() - datetime.fromisoformat(job.started_at)) }}</span>
|
<span name="Runtime">{{ (datetime.utcnow() - datetime.fromisoformat(job.started_at)) }}</span>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% endif %}
|
||||||
<div class="job-constraint u-flex">
|
{% 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">
|
||||||
<label>Material</label>
|
<label>Material</label>
|
||||||
{{ job.filament_name }}
|
{{ job.filament_name }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,7 +35,6 @@
|
||||||
<label>Limits</label>
|
<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
|
{{ 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>
|
</div>
|
||||||
{% endif %}
|
|
||||||
{% if job.user_id != ctx.uid %}
|
{% if job.user_id != ctx.uid %}
|
||||||
<div class="job-user u-flex">
|
<div class="job-user u-flex">
|
||||||
<label>Owner</label>
|
<label>Owner</label>
|
||||||
|
@ -37,7 +42,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="two columns">
|
<div class="two columns u-mv-auto">
|
||||||
<div class="job-status u-flex">
|
<div class="job-status u-flex">
|
||||||
<label for="state">Status</label>
|
<label for="state">Status</label>
|
||||||
<div class="dot {{ macros.job_state(job) }} {{ macros.job_active(job) }} tooltip bottom" data-text="{{ macros.job_state(job) }}" style="--dot-size: 1em;"> </div>
|
<div class="dot {{ macros.job_state(job) }} {{ macros.job_active(job) }} tooltip bottom" data-text="{{ macros.job_state(job) }}" style="--dot-size: 1em;"> </div>
|
||||||
|
|
|
@ -89,10 +89,12 @@ def poll_printers(app: App, db: Db) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
if "error" in status:
|
if "error" in status:
|
||||||
log.error(f"Printer {printer.id} failed to report bed readiness with {status!r}")
|
log.error(
|
||||||
|
f"Printer {printer.id} failed to report bed readiness with {status!r}"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
similarity = status.get("similarity", 0.0) ** 3 # Cube it
|
similarity = status.get("similarity", 0.0) ** 3 # Cube it
|
||||||
return similarity > 0.9
|
return similarity > 0.9
|
||||||
|
|
||||||
printer_job = {}
|
printer_job = {}
|
||||||
|
@ -216,6 +218,21 @@ def push_jobs(app: App, db: Db) -> None:
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
# FIXME: Time since last job ended?
|
||||||
|
if last_level_date := printer.last_level_date:
|
||||||
|
last_level_date = datetime.fromisoformat(last_level_date)
|
||||||
|
|
||||||
|
if not last_level_date or (
|
||||||
|
datetime.utcnow() - last_level_date >= timedela(hours=24)
|
||||||
|
):
|
||||||
|
log.info(f"Printer {printer.id} needs to be leveled...")
|
||||||
|
client.gcode(
|
||||||
|
[
|
||||||
|
"G29",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
db.update_printer_level_date(pid=printer.id)
|
||||||
|
|
||||||
client.select(Path(file.path).name)
|
client.select(Path(file.path).name)
|
||||||
client.start()
|
client.start()
|
||||||
db.start_job(jid=job.id)
|
db.start_job(jid=job.id)
|
||||||
|
@ -275,6 +292,12 @@ def pull_jobs(app: App, db: Db) -> None:
|
||||||
log.info(f"Job {job.id} has succeeded")
|
log.info(f"Job {job.id} has succeeded")
|
||||||
db.finish_job(jid=job.id, state="success")
|
db.finish_job(jid=job.id, state="success")
|
||||||
|
|
||||||
|
elif job_state.get("progress", {}).get("completion", 0.0) < 100.0:
|
||||||
|
time_left = float(
|
||||||
|
job_state.get("progress", {}).get("printTimeLeft", "3600.0")
|
||||||
|
)
|
||||||
|
db.update_job_time_left(jid=job.id, time_left=time_left)
|
||||||
|
|
||||||
elif printer_state.get("error"):
|
elif printer_state.get("error"):
|
||||||
log.warn(f"Job {job.id} has failed")
|
log.warn(f"Job {job.id} has failed")
|
||||||
db.finish_job(jid=job.id, state="failed")
|
db.finish_job(jid=job.id, state="failed")
|
||||||
|
|
Loading…
Reference in a new issue