Use network manager in SliceInfo

CURA-6387
This commit is contained in:
Lipu Fei 2019-05-17 13:50:17 +02:00
parent 77511c2590
commit 6fbce74523
2 changed files with 34 additions and 67 deletions

View file

@ -5,14 +5,13 @@ import json
import os import os
import platform import platform
import time import time
from typing import cast, Optional, Set from typing import cast, Optional, Set, TYPE_CHECKING
from PyQt5.QtCore import pyqtSlot, QObject from PyQt5.QtCore import pyqtSlot, QObject
from PyQt5.QtNetwork import QNetworkRequest
from UM.Extension import Extension from UM.Extension import Extension
from UM.Application import Application
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
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
from UM.PluginRegistry import PluginRegistry from UM.PluginRegistry import PluginRegistry
@ -20,7 +19,8 @@ from UM.Qt.Duration import DurationFormat
from cura import ApplicationMetadata from cura import ApplicationMetadata
from .SliceInfoJob import SliceInfoJob if TYPE_CHECKING:
from PyQt5.QtNetwork import QNetworkReply
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
@ -36,7 +36,8 @@ class SliceInfo(QObject, Extension):
QObject.__init__(self, parent) QObject.__init__(self, parent)
Extension.__init__(self) Extension.__init__(self)
self._application = Application.getInstance() from cura.CuraApplication import CuraApplication
self._application = CuraApplication.getInstance()
self._application.getOutputDeviceManager().writeStarted.connect(self._onWriteStarted) self._application.getOutputDeviceManager().writeStarted.connect(self._onWriteStarted)
self._application.getPreferences().addPreference("info/send_slice_info", True) self._application.getPreferences().addPreference("info/send_slice_info", True)
@ -56,7 +57,7 @@ class SliceInfo(QObject, Extension):
## Perform action based on user input. ## Perform action based on user input.
# Note that clicking "Disable" won't actually disable the data sending, but rather take the user to preferences where they can disable it. # Note that clicking "Disable" won't actually disable the data sending, but rather take the user to preferences where they can disable it.
def messageActionTriggered(self, message_id, action_id): def messageActionTriggered(self, message_id, action_id):
Application.getInstance().getPreferences().setValue("info/asked_send_slice_info", True) self._application.getPreferences().setValue("info/asked_send_slice_info", True)
if action_id == "MoreInfo": if action_id == "MoreInfo":
self.showMoreInfoDialog() self.showMoreInfoDialog()
self.send_slice_info_message.hide() self.send_slice_info_message.hide()
@ -69,7 +70,7 @@ class SliceInfo(QObject, Extension):
def _createDialog(self, qml_name): def _createDialog(self, qml_name):
Logger.log("d", "Creating dialog [%s]", qml_name) Logger.log("d", "Creating dialog [%s]", qml_name)
file_path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), qml_name) file_path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), qml_name)
dialog = Application.getInstance().createQmlComponent(file_path, {"manager": self}) dialog = self._application.createQmlComponent(file_path, {"manager": self})
return dialog return dialog
@pyqtSlot(result = str) @pyqtSlot(result = str)
@ -87,12 +88,10 @@ class SliceInfo(QObject, Extension):
@pyqtSlot(bool) @pyqtSlot(bool)
def setSendSliceInfo(self, enabled: bool): def setSendSliceInfo(self, enabled: bool):
Application.getInstance().getPreferences().setValue("info/send_slice_info", enabled) self._application.getPreferences().setValue("info/send_slice_info", enabled)
def _getUserModifiedSettingKeys(self) -> list: def _getUserModifiedSettingKeys(self) -> list:
from cura.CuraApplication import CuraApplication machine_manager = self._application.getMachineManager()
application = cast(CuraApplication, Application.getInstance())
machine_manager = application.getMachineManager()
global_stack = machine_manager.activeMachine global_stack = machine_manager.activeMachine
user_modified_setting_keys = set() # type: Set[str] user_modified_setting_keys = set() # type: Set[str]
@ -106,30 +105,28 @@ class SliceInfo(QObject, Extension):
def _onWriteStarted(self, output_device): def _onWriteStarted(self, output_device):
try: try:
if not Application.getInstance().getPreferences().getValue("info/send_slice_info"): if not self._application.getPreferences().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
from cura.CuraApplication import CuraApplication machine_manager = self._application.getMachineManager()
application = cast(CuraApplication, Application.getInstance()) print_information = self._application.getPrintInformation()
machine_manager = application.getMachineManager()
print_information = application.getPrintInformation()
global_stack = machine_manager.activeMachine global_stack = machine_manager.activeMachine
data = dict() # The data that we're going to submit. data = dict() # The data that we're going to submit.
data["time_stamp"] = time.time() data["time_stamp"] = time.time()
data["schema_version"] = 0 data["schema_version"] = 0
data["cura_version"] = application.getVersion() data["cura_version"] = self._application.getVersion()
data["cura_build_type"] = ApplicationMetadata.CuraBuildType data["cura_build_type"] = ApplicationMetadata.CuraBuildType
active_mode = Application.getInstance().getPreferences().getValue("cura/active_mode") active_mode = self._application.getPreferences().getValue("cura/active_mode")
if active_mode == 0: if active_mode == 0:
data["active_mode"] = "recommended" data["active_mode"] = "recommended"
else: else:
data["active_mode"] = "custom" data["active_mode"] = "custom"
data["camera_view"] = application.getPreferences().getValue("general/camera_perspective_mode") data["camera_view"] = self._application.getPreferences().getValue("general/camera_perspective_mode")
if data["camera_view"] == "orthographic": if data["camera_view"] == "orthographic":
data["camera_view"] = "orthogonal" #The database still only recognises the old name "orthogonal". data["camera_view"] = "orthogonal" #The database still only recognises the old name "orthogonal".
@ -142,7 +139,7 @@ class SliceInfo(QObject, Extension):
machine_settings_changed_by_user = True machine_settings_changed_by_user = True
data["machine_settings_changed_by_user"] = machine_settings_changed_by_user data["machine_settings_changed_by_user"] = machine_settings_changed_by_user
data["language"] = Application.getInstance().getPreferences().getValue("general/language") data["language"] = self._application.getPreferences().getValue("general/language")
data["os"] = {"type": platform.system(), "version": platform.version()} data["os"] = {"type": platform.system(), "version": platform.version()}
data["active_machine"] = {"definition_id": global_stack.definition.getId(), data["active_machine"] = {"definition_id": global_stack.definition.getId(),
@ -184,7 +181,7 @@ class SliceInfo(QObject, Extension):
data["models"] = [] data["models"] = []
# Listing all files placed on the build plate # Listing all files placed on the build plate
for node in DepthFirstIterator(application.getController().getScene().getRoot()): for node in DepthFirstIterator(self._application.getController().getScene().getRoot()):
if node.callDecoration("isSliceable"): if node.callDecoration("isSliceable"):
model = dict() model = dict()
model["hash"] = node.getMeshData().getHash() model["hash"] = node.getMeshData().getHash()
@ -263,10 +260,23 @@ class SliceInfo(QObject, Extension):
# Convert data to bytes # Convert data to bytes
binary_data = json.dumps(data).encode("utf-8") binary_data = json.dumps(data).encode("utf-8")
# Sending slice info non-blocking # Send slice info non-blocking
reportJob = SliceInfoJob(self.info_url, binary_data) network_manager = self._application.getHttpNetworkRequestManager()
reportJob.start() network_manager.post(self.info_url, data = binary_data,
callback = self._onRequestFinished, error_callback = self._onRequestError)
except Exception: 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.logException("e", "Exception raised while sending slice info.") # 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.
def _onRequestFinished(self, reply: "QNetworkReply") -> None:
status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
if status_code == 200:
Logger.log("i", "SliceInfo sent successfully")
return
data = reply.readAll().data().decode("utf-8")
Logger.log("e", "SliceInfo request failed, status code %s, data: %s", status_code, data)
def _onRequestError(self, reply: "QNetworkReply", error: "QNetworkReply.NetworkError") -> None:
Logger.log("e", "Got error for SliceInfo request: %s", reply.errorString())

View file

@ -1,43 +0,0 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.Job import Job
from UM.Logger import Logger
from UM.Platform import Platform
import ssl
import urllib.request
import urllib.error
import certifi
class SliceInfoJob(Job):
def __init__(self, url, data):
super().__init__()
self._url = url
self._data = data
def run(self):
if not self._url or not self._data:
Logger.log("e", "URL or DATA for sending slice info was not set!")
return
# CURA-6698 Create an SSL context and use certifi CA certificates for verification.
context = ssl.SSLContext(protocol = ssl.PROTOCOL_TLSv1_2)
context.load_verify_locations(cafile = certifi.where())
# Submit data
kwoptions = {"data": self._data,
"timeout": 5,
"context": context}
Logger.log("i", "Sending anonymous slice info to [%s]...", self._url)
try:
f = urllib.request.urlopen(self._url, **kwoptions)
Logger.log("i", "Sent anonymous slice info.")
f.close()
except urllib.error.HTTPError:
Logger.logException("e", "An HTTP error occurred while trying to send slice information")
except Exception: # We don't want any exception to cause problems
Logger.logException("e", "An exception occurred while trying to send slice information")