Merge pull request #810 from thopiekar/master-CURA-1615

[CURA-1615] Plugins: Updating GCodeProfileReader and SliceInfo
This commit is contained in:
Aldo Hoeben 2016-06-23 09:45:56 +02:00 committed by GitHub
commit 097bcad427
4 changed files with 40 additions and 48 deletions

View File

@ -1,19 +1,23 @@
# Copyright (c) 2015 Ultimaker B.V. # Copyright (c) 2015 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher. # Cura is released under the terms of the AGPLv3 or higher.
from UM.Application import Application #To get the machine manager to create the new profile in. import os
from UM.Settings.Profile import Profile
from UM.Settings.ProfileReader import ProfileReader
from UM.Logger import Logger
import re #Regular expressions for parsing escape characters in the settings. import re #Regular expressions for parsing escape characters in the settings.
from UM.Application import Application #To get the machine manager to create the new profile in.
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Logger import Logger
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
from cura.ProfileReader import ProfileReader
## A class that reads profile data from g-code files. ## A class that reads profile data from g-code files.
# #
# It reads the profile data from g-code files and stores it in a new profile. # It reads the profile data from g-code files and stores it in a new profile.
# This class currently does not process the rest of the g-code in any way. # This class currently does not process the rest of the g-code in any way.
class GCodeProfileReader(ProfileReader): class GCodeProfileReader(ProfileReader):
## The file format version of the serialised g-code. ## The file format version of the serialized g-code.
# #
# It can only read settings with the same version as the version it was # It can only read settings with the same version as the version it was
# written with. If the file format is changed in a way that breaks reverse # written with. If the file format is changed in a way that breaks reverse
@ -51,31 +55,36 @@ class GCodeProfileReader(ProfileReader):
# Loading all settings from the file. # Loading all settings from the file.
# They are all at the end, but Python has no reverse seek any more since Python3. # They are all at the end, but Python has no reverse seek any more since Python3.
# TODO: Consider moving settings to the start? # TODO: Consider moving settings to the start?
serialised = "" # Will be filled with the serialised profile. serialized = "" # Will be filled with the serialized profile.
try: try:
with open(file_name) as f: with open(file_name) as f:
for line in f: for line in f:
if line.startswith(prefix): if line.startswith(prefix):
# Remove the prefix and the newline from the line and add it to the rest. # Remove the prefix and the newline from the line and add it to the rest.
serialised += line[prefix_length : -1] serialized += line[prefix_length : -1]
except IOError as e: except IOError as e:
Logger.log("e", "Unable to open file %s for reading: %s", file_name, str(e)) Logger.log("e", "Unable to open file %s for reading: %s", file_name, str(e))
return None return None
# Un-escape the serialised profile. # Un-escape the serialized profile.
pattern = re.compile("|".join(GCodeProfileReader.escape_characters.keys())) pattern = re.compile("|".join(GCodeProfileReader.escape_characters.keys()))
# Perform the replacement with a regular expression. # Perform the replacement with a regular expression.
serialised = pattern.sub(lambda m: GCodeProfileReader.escape_characters[re.escape(m.group(0))], serialised) serialized = pattern.sub(lambda m: GCodeProfileReader.escape_characters[re.escape(m.group(0))], serialized)
Logger.log("i", "Serialized the following from %s: %s" %(file_name, repr(serialized)))
# Apply the changes to the current profile. # Create an empty profile - the id will be changed later
profile = Profile(machine_manager = Application.getInstance().getMachineManager(), read_only = False) profile = InstanceContainer("")
profile.addMetaDataEntry("type", "quality")
try: try:
profile.unserialise(serialised) profile.deserialize(serialized)
profile.setType(None) # Force type to none so it's correctly added.
profile.setReadOnly(False)
profile.setDirty(True)
except Exception as e: # Not a valid g-code file. except Exception as e: # Not a valid g-code file.
Logger.log("e", "Unable to serialise the profile: %s", str(e)) Logger.log("e", "Unable to serialise the profile: %s", str(e))
return None return None
return profile
#Creating a unique name using the filename of the GCode
new_name = catalog.i18nc("@label", "Custom profile (%s)") %(os.path.splitext(os.path.basename(file_name))[0])
profile.setName(new_name)
profile._id = new_name
return profile

View File

@ -13,7 +13,7 @@ def getMetaData():
"author": "Ultimaker", "author": "Ultimaker",
"version": "1.0", "version": "1.0",
"description": catalog.i18nc("@info:whatsthis", "Provides support for importing profiles from g-code files."), "description": catalog.i18nc("@info:whatsthis", "Provides support for importing profiles from g-code files."),
"api": 2 "api": 3
}, },
"profile_reader": [ "profile_reader": [
{ {

View File

@ -8,6 +8,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Scene.SceneNode import SceneNode from UM.Scene.SceneNode import SceneNode
from UM.Message import Message from UM.Message import Message
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from UM.Logger import Logger
import collections import collections
import json import json
@ -25,6 +26,8 @@ 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"
def __init__(self): def __init__(self):
super().__init__() super().__init__()
Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._onWriteStarted) Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._onWriteStarted)
@ -43,34 +46,14 @@ class SliceInfo(Extension):
def _onWriteStarted(self, output_device): def _onWriteStarted(self, output_device):
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.")
return # Do nothing, user does not want to send data return # Do nothing, user does not want to send data
settings = Application.getInstance().getMachineManager().getWorkingProfile()
# Load all machine definitions and put them in machine_settings dict global_container_stack = Application.getInstance().getGlobalContainerStack()
#setting_file_name = Application.getInstance().getActiveMachineInstance().getMachineSettings()._json_file
machine_settings = {}
#with open(setting_file_name, "rt", -1, "utf-8") as f:
# data = json.load(f, object_pairs_hook = collections.OrderedDict)
#machine_settings[os.path.basename(setting_file_name)] = copy.deepcopy(data)
active_machine_definition= Application.getInstance().getMachineManager().getActiveMachineInstance().getMachineDefinition()
data = active_machine_definition._json_data
# Loop through inherited json files
setting_file_name = active_machine_definition._path
while True:
if "inherits" in data:
inherited_setting_file_name = os.path.dirname(setting_file_name) + "/" + data["inherits"]
with open(inherited_setting_file_name, "rt", -1, "utf-8") as f:
data = json.load(f, object_pairs_hook = collections.OrderedDict)
machine_settings[os.path.basename(inherited_setting_file_name)] = copy.deepcopy(data)
else:
break
profile_values = settings.getChangedSettings() # TODO: @UnusedVariable
# Get total material used (in mm^3) # Get total material used (in mm^3)
print_information = Application.getInstance().getPrintInformation() print_information = Application.getInstance().getPrintInformation()
material_radius = 0.5 * settings.getSettingValue("material_diameter") material_radius = 0.5 * global_container_stack.getProperty("material_diameter", "value")
material_used = math.pi * material_radius * material_radius * print_information.materialAmount #Volume of material used material_used = math.pi * material_radius * material_radius * print_information.materialAmount #Volume of material used
# Get model information (bounding boxes, hashes and transformation matrix) # Get model information (bounding boxes, hashes and transformation matrix)
@ -99,10 +82,10 @@ class SliceInfo(Extension):
"processor": platform.processor(), "processor": platform.processor(),
"machine": platform.machine(), "machine": platform.machine(),
"platform": platform.platform(), "platform": platform.platform(),
"machine_settings": json.dumps(machine_settings), "global_settings": global_container_stack.serialize(),
"version": Application.getInstance().getVersion(), "version": Application.getInstance().getVersion(),
"modelhash": "None", "modelhash": "None",
"printtime": str(print_information.currentPrintTime), "printtime": print_information.currentPrintTime.getDisplayString(),
"filament": material_used, "filament": material_used,
"language": Preferences.getInstance().getValue("general/language"), "language": Preferences.getInstance().getValue("general/language"),
"materials_profiles ": {} "materials_profiles ": {}
@ -114,8 +97,8 @@ class SliceInfo(Extension):
# Submit data # Submit data
try: try:
f = urllib.request.urlopen("https://stats.youmagine.com/curastats/slice", data = binary_data, timeout = 1) f = urllib.request.urlopen(self.info_url, data = binary_data, timeout = 1)
Logger.log("i", "Sent anonymous slice info to %s", self.info_url)
f.close()
except Exception as e: except Exception as e:
print("Exception occured", e) Logger.logException("e", e)
f.close()

View File

@ -11,7 +11,7 @@ def getMetaData():
"author": "Ultimaker", "author": "Ultimaker",
"version": "1.0", "version": "1.0",
"description": catalog.i18nc("@info:whatsthis", "Submits anonymous slice info. Can be disabled through preferences."), "description": catalog.i18nc("@info:whatsthis", "Submits anonymous slice info. Can be disabled through preferences."),
"api": 2 "api": 3
} }
} }