Grotti 2.10.0: Orca-Senden, Slice-Ordner, ED-Strom, Hygiene.
Slice-Watch mit Ordnern/Filtern, Orca-Nachbearbeitung, Cockpit-Verlauf mit ED, Zeitzone im Browser. Tasten-Grenze und README-API angeglichen, toter Code entfernt, Requirements gepinnt.
This commit is contained in:
1 parent
efd0801cd1
commit
9e22cebb81
48 files changed
+2259
-422
No files matched your search
+67
-3
@@ -190,7 +190,11 @@ def create_app(cfg):
|
||||
if not user:
|
||||
if wants_json() or path.startswith("/api/"):
|
||||
return jsonify({"error": "Anmeldung nötig.", "code": "auth"}), 401
|
||||
return redirect(url_for("login_page", next=path))
|
||||
# Query behalten (z. B. /dateien?file=12 nach Orca-Upload)
|
||||
next_path = path
|
||||
if request.query_string:
|
||||
next_path = path + "?" + request.query_string.decode("utf-8", "replace")
|
||||
return redirect(url_for("login_page", next=next_path))
|
||||
|
||||
g.user = user
|
||||
ensure_csrf()
|
||||
@@ -490,6 +494,7 @@ def create_app(cfg):
|
||||
"Anleitung-Oberflaeche",
|
||||
"Anleitung-Wand",
|
||||
"Anleitung-Dateien",
|
||||
"Anleitung-Orca",
|
||||
"Anleitung-ACE",
|
||||
"Anleitung-Warteschlange",
|
||||
"Anleitung-Material",
|
||||
@@ -510,6 +515,7 @@ def create_app(cfg):
|
||||
"Anleitung-Oberflaeche": "Oberfläche",
|
||||
"Anleitung-Wand": "Druckerwand",
|
||||
"Anleitung-Dateien": "Dateien senden",
|
||||
"Anleitung-Orca": "Orca an Grotti",
|
||||
"Anleitung-ACE": "ACE und Spulen",
|
||||
"Anleitung-Warteschlange": "Warteschlange",
|
||||
"Anleitung-Material": "Material und mehr",
|
||||
@@ -695,8 +701,15 @@ def create_app(cfg):
|
||||
alerts = data.get("alerts") if isinstance(data.get("alerts"), dict) else None
|
||||
auto_queue = data.get("auto_queue") if "auto_queue" in data else None
|
||||
fqdn = data.get("fqdn") if "fqdn" in data else None
|
||||
watch_dir = data.get("watch_dir") if "watch_dir" in data else None
|
||||
return jsonify(grotti_config.save_settings(
|
||||
cfg, energy=energy, telegram=telegram, alerts=alerts, auto_queue=auto_queue, fqdn=fqdn,
|
||||
cfg,
|
||||
energy=energy,
|
||||
telegram=telegram,
|
||||
alerts=alerts,
|
||||
auto_queue=auto_queue,
|
||||
fqdn=fqdn,
|
||||
watch_dir=watch_dir,
|
||||
))
|
||||
|
||||
@app.post("/api/v1/telegram/test")
|
||||
@@ -906,7 +919,7 @@ def create_app(cfg):
|
||||
@app.get("/api/v1/dateien")
|
||||
def file_list():
|
||||
library.sync_watch(conn(), cfg, force=False)
|
||||
return jsonify(store.list_files(conn()))
|
||||
return jsonify(store.list_files(conn(), watch_dir=cfg.get("watch_dir")))
|
||||
|
||||
@app.post("/api/v1/dateien/neu-lesen")
|
||||
def file_rescan():
|
||||
@@ -914,6 +927,31 @@ def create_app(cfg):
|
||||
result["metadaten"] = library.refresh_file_meta(conn(), force=True)
|
||||
return jsonify(result)
|
||||
|
||||
@app.get("/api/v1/dateien/ordner")
|
||||
def file_folders():
|
||||
return jsonify({"folders": library.list_folders(cfg)})
|
||||
|
||||
@app.post("/api/v1/dateien/ordner")
|
||||
def file_folder_create():
|
||||
data = body()
|
||||
folder = library.create_folder(cfg, data.get("folder"))
|
||||
return jsonify({"folder": folder, "folders": library.list_folders(cfg)}), 201
|
||||
|
||||
@app.delete("/api/v1/dateien/ordner")
|
||||
def file_folder_delete():
|
||||
data = body()
|
||||
folder = library.delete_folder(cfg, data.get("folder"))
|
||||
return jsonify({"folder": folder, "folders": library.list_folders(cfg)})
|
||||
|
||||
@app.post("/api/v1/dateien/<int:file_id>/verschieben")
|
||||
def file_move(file_id):
|
||||
data = body()
|
||||
folder = data.get("folder")
|
||||
if folder is None:
|
||||
folder = ""
|
||||
moved = library.move_file(conn(), cfg, file_id, folder)
|
||||
return jsonify(moved)
|
||||
|
||||
@app.post("/api/v1/dateien")
|
||||
def file_upload():
|
||||
upload = request.files.get("file")
|
||||
@@ -1799,6 +1837,28 @@ def create_app(cfg):
|
||||
def run_list():
|
||||
return jsonify(store.list_runs(conn()))
|
||||
|
||||
@app.get("/api/v1/laeufe/aktuell")
|
||||
def run_aktuell():
|
||||
"""Aktueller oder letzter Temperatur-/ED-Verlauf fürs Cockpit (host=)."""
|
||||
host = require_host(request.args.get("host", ""))
|
||||
run = store.latest_run_for_host(conn(), host)
|
||||
if not run:
|
||||
return jsonify({"run": None, "samples": [], "energy": None})
|
||||
run_id = run["id"]
|
||||
samples = store.list_run_samples(conn(), run_id)
|
||||
from grotti.cost import energy_estimate
|
||||
|
||||
energy = energy_estimate(run.get("duration_s"), cfg["energy"], samples)
|
||||
if len(samples) > 180:
|
||||
step = max(1, len(samples) // 120)
|
||||
samples = samples[::step]
|
||||
return jsonify({
|
||||
"run": run,
|
||||
"samples": samples,
|
||||
"energy": energy,
|
||||
"sample_count": int(run.get("_sample_count") or len(samples)),
|
||||
})
|
||||
|
||||
@app.get("/api/v1/laeufe/<int:run_id>")
|
||||
def run_get(run_id):
|
||||
row = store.get_run_row(conn(), run_id)
|
||||
@@ -1814,6 +1874,9 @@ def create_app(cfg):
|
||||
file_row = store.get_file_row(conn(), run["file_id"]) if run.get("file_id") else None
|
||||
project = store.get_project(conn(), run["project_id"]) if run.get("project_id") else None
|
||||
samples = store.list_run_samples(conn(), run_id)
|
||||
from grotti.cost import energy_estimate
|
||||
|
||||
energy = energy_estimate(run.get("duration_s"), cfg["energy"], samples)
|
||||
# Anzeige auf ca. 1 Punkt / Minute verdichten
|
||||
if len(samples) > 180:
|
||||
step = max(1, len(samples) // 120)
|
||||
@@ -1827,6 +1890,7 @@ def create_app(cfg):
|
||||
"events": store.list_run_events(conn(), run_id),
|
||||
"file": store.file_out(file_row) if file_row else None,
|
||||
"project": project,
|
||||
"energy": energy,
|
||||
})
|
||||
|
||||
@app.post("/api/v1/laeufe/abgleich")
|
||||
|
||||
Reference in new issue
Block a user