Dokončeno!
Povedlo se mi sestavit program, který počítá hmotnost využitého filamentu za daný časový úsek.
Jak to funguje?
Po spuštění python kódu se Vás program zeptá z kolika dní z minulosti by jste chtěli data zobrazit. Po zadání odešle žádost do Vašeho Karmen API získá potřebné informace a během cca 45 sekund Vám zobrazí sečtený počet vytištěných nesmazaných souborů a kolik filamentu spotřebovaly.
Před spuštěním kódu je potřeba do něj vložit API klíč a Vaše group_id.
import subprocess
import json
from datetime import datetime, timedelta
def get_print_jobs(page):
curl_command = [
"curl", "-k", "-H", "Authorization: Token <api_key>",
f"https://backend.next.karmen.tech/api/2/groups/<group_id>/print-jobs/?page={page}"
]
result = subprocess.run(curl_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode != 0:
return None
return json.loads(result.stdout.decode())
def get_files(page):
curl_command = [
"curl", "-k", "-H", "Authorization: Token <api_key>",
f"https://backend.next.karmen.tech/api/2/groups/<group_id>/files/?page={page}"
]
result = subprocess.run(curl_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode != 0:
return None
return json.loads(result.stdout.decode())
def get_print_jobs_within_days(days_past):
id_file_started_on_list = []
page = 1
cutoff_date = datetime.now() - timedelta(days=days_past)
while True:
print_jobs_data = get_print_jobs(page)
if not print_jobs_data or 'results' not in print_jobs_data:
break
print_jobs = print_jobs_data['results']
for print_job in print_jobs:
job_id = print_job.get('id', None)
started_on = print_job.get('started_on', None)
file_id = print_job.get('file_id', None)
if job_id and started_on and file_id:
job_started_on = datetime.strptime(started_on, "%Y-%m-%dT%H:%M:%S.%fZ")
if job_started_on < cutoff_date:
return id_file_started_on_list
id_file_started_on_list.append({'id': job_id, 'file_id': file_id, 'started_on': started_on})
if print_jobs_data.get('next'):
page += 1
else:
break
return id_file_started_on_list
def get_filament_weight_for_files(print_jobs):
total_filament_used = 0
page = 1
file_id_to_filament = {}
while True:
files_data = get_files(page)
if not files_data or 'results' not in files_data:
break
files = files_data['results']
for file in files:
file_id = file.get('id')
filament_used = file.get('filament_used_g', 0)
if file_id:
file_id_to_filament[file_id] = filament_used
if files_data.get('next'):
page += 1
else:
break
for print_job in print_jobs:
file_id = print_job['file_id']
if file_id in file_id_to_filament:
total_filament_used += file_id_to_filament[file_id]
return total_filament_used
if __name__ == "__main__":
days = int(input("Enter the number of days to filter print jobs from: "))
print_jobs = get_print_jobs_within_days(days)
total_filament_used = get_filament_weight_for_files(print_jobs)
print(f"Total print jobs in the past {days} days: {len(print_jobs)}")
print(f"Total filament used in the past {days} days: {round(total_filament_used)}g")
Problém z posledního postu a tím i další menší problémy, které zbývaly, jsem vyřešil tím, že jsem předělal celou strukturu.
Začal jsem tedy tím, že jsem vytvořil funkce, která získávala časy a file_id z print-jobs a z nich rovnou sestavila list tisků, které se staly za dobu danou uživatelem. Také jsem otočil procházení stránek a zavedl jsem zastavení poté co se dostane za časový horizont, čímž se celý proces velmi zrychlil.
Až po těchto všech úkonech se přiřadí hmotnosti filamentu z files pomocí shodných id. Počítá se s tím, že soubory mohou být tisknuty víckrát a proto se id může přiřadit i k více tiskům. Následně se vše sečte a zobrazí se výsledná data uživateli.
Patrik