Merge branch 'CURA-3858' of github.com:Ultimaker/Cura

This commit is contained in:
Jaime van Kessel 2017-07-07 13:44:00 +02:00
commit 4275555f44

View File

@ -2,6 +2,7 @@
# Cura is released under the terms of the AGPLv3 or higher. # Cura is released under the terms of the AGPLv3 or higher.
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from cura.Settings.ExtruderManager import ExtruderManager
from UM.Extension import Extension from UM.Extension import Extension
from UM.Application import Application from UM.Application import Application
@ -11,6 +12,8 @@ from UM.Message import Message
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from UM.Logger import Logger from UM.Logger import Logger
import time
from UM.Qt.Duration import DurationFormat from UM.Qt.Duration import DurationFormat
from .SliceInfoJob import SliceInfoJob from .SliceInfoJob import SliceInfoJob
@ -28,7 +31,7 @@ catalog = i18nCatalog("cura")
# The data is only sent when the user in question gave permission to do so. All data is anonymous and # The data is only sent when the user in question gave permission to do so. All data is anonymous and
# no model files are being sent (Just a SHA256 hash of the model). # no model files are being sent (Just a SHA256 hash of the model).
class SliceInfo(Extension): class SliceInfo(Extension):
info_url = "https://stats.youmagine.com/curastats/slice" info_url = "http://stats.ultimaker.com/api/cura"
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@ -50,61 +53,139 @@ class SliceInfo(Extension):
try: try:
if not Preferences.getInstance().getValue("info/send_slice_info"): if not Preferences.getInstance().getValue("info/send_slice_info"):
Logger.log("d", "'info/send_slice_info' is turned off.") Logger.log("d", "'info/send_slice_info' is turned off.")
return # Do nothing, user does not want to send data return # Do nothing, user does not want to send data
# Listing all files placed on the buildplate
modelhashes = []
for node in DepthFirstIterator(CuraApplication.getInstance().getController().getScene().getRoot()):
if node.callDecoration("isSliceable"):
modelhashes.append(node.getMeshData().getHash())
# Creating md5sums and formatting them as discussed on JIRA
modelhash_formatted = ",".join(modelhashes)
global_container_stack = Application.getInstance().getGlobalContainerStack() global_container_stack = Application.getInstance().getGlobalContainerStack()
# Get total material used (in mm^3)
print_information = Application.getInstance().getPrintInformation() print_information = Application.getInstance().getPrintInformation()
material_radius = 0.5 * global_container_stack.getProperty("material_diameter", "value")
# Send material per extruder data = dict() # The data that we're going to submit.
material_used = [str(math.pi * material_radius * material_radius * material_length) for material_length in print_information.materialLengths] data["time_stamp"] = time.time()
material_used = ",".join(material_used) data["schema_version"] = 0
data["cura_version"] = Application.getInstance().getVersion()
containers = { "": global_container_stack.serialize() } active_mode = Preferences.getInstance().getValue("cura/active_mode")
for container in global_container_stack.getContainers(): if active_mode == 0:
container_id = container.getId() data["active_mode"] = "recommended"
try: else:
container_serialized = container.serialize() data["active_mode"] = "custom"
except NotImplementedError:
Logger.log("w", "Container %s could not be serialized!", container_id)
continue
if container_serialized:
containers[container_id] = container_serialized
else:
Logger.log("i", "No data found in %s to be serialized!", container_id)
# Bundle the collected data data["machine_settings_changed_by_user"] = global_container_stack.definitionChanges.getId() != "empty"
submitted_data = { data["language"] = Preferences.getInstance().getValue("general/language")
"processor": platform.processor(), data["os"] = {"type": platform.system(), "version": platform.version()}
"machine": platform.machine(),
"platform": platform.platform(), data["active_machine"] = {"definition_id": global_container_stack.definition.getId(), "manufacturer": global_container_stack.definition.getMetaData().get("manufacturer","")}
"settings": json.dumps(containers), # bundle of containers with their serialized contents
"version": Application.getInstance().getVersion(), data["extruders"] = []
"modelhash": modelhash_formatted, extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId()))
"printtime": print_information.currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601), extruders = sorted(extruders, key = lambda extruder: extruder.getMetaDataEntry("position"))
"filament": material_used,
"language": Preferences.getInstance().getValue("general/language"), if not extruders:
} extruders = [global_container_stack]
for extruder in extruders:
extruder_dict = dict()
extruder_dict["active"] = ExtruderManager.getInstance().getActiveExtruderStack() == extruder
extruder_dict["material"] = {"GUID": extruder.material.getMetaData().get("GUID", ""),
"type": extruder.material.getMetaData().get("material", ""),
"brand": extruder.material.getMetaData().get("brand", "")
}
extruder_dict["material_used"] = print_information.materialLengths[int(extruder.getMetaDataEntry("position", "0"))]
extruder_dict["variant"] = extruder.variant.getName()
extruder_dict["nozzle_size"] = extruder.getProperty("machine_nozzle_size", "value")
extruder_settings = dict()
extruder_settings["wall_line_count"] = extruder.getProperty("wall_line_count", "value")
extruder_settings["retraction_enable"] = extruder.getProperty("retraction_enable", "value")
extruder_settings["infill_sparse_density"] = extruder.getProperty("infill_sparse_density", "value")
extruder_settings["infill_pattern"] = extruder.getProperty("infill_pattern", "value")
extruder_settings["gradual_infill_steps"] = extruder.getProperty("gradual_infill_steps", "value")
extruder_settings["default_material_print_temperature"] = extruder.getProperty("default_material_print_temperature", "value")
extruder_settings["material_print_temperature"] = extruder.getProperty("material_print_temperature", "value")
extruder_dict["extruder_settings"] = extruder_settings
data["extruders"].append(extruder_dict)
data["quality_profile"] = global_container_stack.quality.getMetaData().get("quality_type")
data["models"] = []
# Listing all files placed on the build plate
for node in DepthFirstIterator(CuraApplication.getInstance().getController().getScene().getRoot()):
if node.callDecoration("isSliceable"):
model = dict()
model["hash"] = node.getMeshData().getHash()
bounding_box = node.getBoundingBox()
model["bounding_box"] = {"minimum": {"x": bounding_box.minimum.x,
"y": bounding_box.minimum.y,
"z": bounding_box.minimum.z},
"maximum": {"x": bounding_box.maximum.x,
"y": bounding_box.maximum.y,
"z": bounding_box.maximum.z}}
model["transformation"] = {"data": str(node.getWorldTransformation().getData()).replace("\n", "")}
extruder_position = node.callDecoration("getActiveExtruderPosition")
model["extruder"] = 0 if extruder_position is None else int(extruder_position)
model_settings = dict()
model_stack = node.callDecoration("getStack")
if model_stack:
model_settings["support_enabled"] = model_stack.getProperty("support_enable", "value")
model_settings["support_extruder_nr"] = int(model_stack.getProperty("support_extruder_nr", "value"))
# Mesh modifiers;
model_settings["infill_mesh"] = model_stack.getProperty("infill_mesh", "value")
model_settings["cutting_mesh"] = model_stack.getProperty("cutting_mesh", "value")
model_settings["support_mesh"] = model_stack.getProperty("support_mesh", "value")
model_settings["anti_overhang_mesh"] = model_stack.getProperty("anti_overhang_mesh", "value")
model_settings["wall_line_count"] = model_stack.getProperty("wall_line_count", "value")
model_settings["retraction_enable"] = model_stack.getProperty("retraction_enable", "value")
# Infill settings
model_settings["infill_sparse_density"] = model_stack.getProperty("infill_sparse_density", "value")
model_settings["infill_pattern"] = model_stack.getProperty("infill_pattern", "value")
model_settings["gradual_infill_steps"] = model_stack.getProperty("gradual_infill_steps", "value")
model["model_settings"] = model_settings
data["models"].append(model)
print_times = print_information.printTimesPerFeature
data["print_times"] = {"travel": int(print_times["travel"].getDisplayString(DurationFormat.Format.Seconds)),
"support": int(print_times["support"].getDisplayString(DurationFormat.Format.Seconds)),
"infill": int(print_times["infill"].getDisplayString(DurationFormat.Format.Seconds)),
"total": int(print_information.currentPrintTime.getDisplayString(DurationFormat.Format.Seconds))}
print_settings = dict()
print_settings["layer_height"] = global_container_stack.getProperty("layer_height", "value")
# Support settings
print_settings["support_enabled"] = global_container_stack.getProperty("support_enable", "value")
print_settings["support_extruder_nr"] = int(global_container_stack.getProperty("support_extruder_nr", "value"))
# Platform adhesion settings
print_settings["adhesion_type"] = global_container_stack.getProperty("adhesion_type", "value")
# Shell settings
print_settings["wall_line_count"] = global_container_stack.getProperty("wall_line_count", "value")
print_settings["retraction_enable"] = global_container_stack.getProperty("retraction_enable", "value")
# Prime tower settings
print_settings["prime_tower_enable"] = global_container_stack.getProperty("prime_tower_enable", "value")
# Infill settings
print_settings["infill_sparse_density"] = global_container_stack.getProperty("infill_sparse_density", "value")
print_settings["infill_pattern"] = global_container_stack.getProperty("infill_pattern", "value")
print_settings["gradual_infill_steps"] = global_container_stack.getProperty("gradual_infill_steps", "value")
print_settings["print_sequence"] = global_container_stack.getProperty("print_sequence", "value")
data["print_settings"] = print_settings
# Convert data to bytes # Convert data to bytes
submitted_data = urllib.parse.urlencode(submitted_data) binary_data = json.dumps(data).encode("utf-8")
binary_data = submitted_data.encode("utf-8")
# Sending slice info non-blocking # Sending slice info non-blocking
reportJob = SliceInfoJob(self.info_url, binary_data) reportJob = SliceInfoJob(self.info_url, binary_data)
reportJob.start() reportJob.start()
except Exception as e: except Exception:
# We really can't afford to have a mistake here, as this would break the sending of g-code to a device # We really can't afford to have a mistake here, as this would break the sending of g-code to a device
# (Either saving or directly to a printer). The functionality of the slice data is not *that* important. # (Either saving or directly to a printer). The functionality of the slice data is not *that* important.
Logger.log("e", "Exception raised while sending slice info: %s" %(repr(e))) # But we should be notified about these problems of course. Logger.logException("e", "Exception raised while sending slice info.") # But we should be notified about these problems of course.