diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 411146d0653..81c0ca05c83 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -1,11 +1,12 @@ # Copyright (c) 2023 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. +import datetime import json import os import platform import time -from typing import Optional, Set, TYPE_CHECKING +from typing import Any, Optional, Set, TYPE_CHECKING from PyQt6.QtCore import pyqtSlot, QObject from PyQt6.QtNetwork import QNetworkRequest @@ -33,7 +34,18 @@ class SliceInfo(QObject, Extension): no model files are being sent (Just a SHA256 hash of the model). """ - info_url = "https://stats.ultimaker.com/api/cura" + info_url = "https://statistics.ultimaker.com/api/v2/cura/slice" + + _adjust_flattened_names = { + "extruders_extruder": "extruders", + "extruders_settings": "extruders", + "models_model": "models", + "models_transformation_data": "models_transformation", + "print_settings_": "", + "print_times": "print_time", + "active_machine_": "", + "slice_uuid": "slice_id", + } def __init__(self, parent = None): QObject.__init__(self, parent) @@ -112,6 +124,26 @@ def _getUserModifiedSettingKeys(self) -> list: return list(sorted(user_modified_setting_keys)) + def _flattenData(self, data: Any, result: dict, current_flat_key: Optional[str] = None, lift_list: bool = False) -> None: + if isinstance(data, dict): + for key, value in data.items(): + total_flat_key = key if current_flat_key is None else f"{current_flat_key}_{key}" + self._flattenData(value, result, total_flat_key, lift_list) + elif isinstance(data, list): + for item in data: + self._flattenData(item, result, current_flat_key, True) + else: + actual_flat_key = current_flat_key.lower() + for key, value in self._adjust_flattened_names.items(): + if actual_flat_key.startswith(key): + actual_flat_key = actual_flat_key.replace(key, value) + if lift_list: + if actual_flat_key not in result: + result[actual_flat_key] = [] + result[actual_flat_key].append(data) + else: + result[actual_flat_key] = data + def _onWriteStarted(self, output_device): try: if not self._application.getPreferences().getValue("info/send_slice_info"): @@ -125,8 +157,7 @@ def _onWriteStarted(self, output_device): global_stack = machine_manager.activeMachine data = dict() # The data that we're going to submit. - data["time_stamp"] = time.time() - data["schema_version"] = 0 + data["schema_version"] = 1000 data["cura_version"] = self._application.getVersion() data["cura_build_type"] = ApplicationMetadata.CuraBuildType org_id = user_profile.get("organization_id", None) if user_profile else None @@ -298,6 +329,11 @@ def _onWriteStarted(self, output_device): "time_backend": int(round(time_backend)), } + # Massage data into format used in the DB: + flat_data = dict() + self._flattenData(data, flat_data) + data = flat_data + # Convert data to bytes binary_data = json.dumps(data).encode("utf-8")