Merge branch 'new_firmware_notification'

This commit is contained in:
ChrisTerBeke 2017-09-14 13:14:32 +02:00
commit 931232ed4d
4 changed files with 159 additions and 0 deletions

View File

@ -0,0 +1,49 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from UM.Extension import Extension
from UM.Preferences import Preferences
from UM.Logger import Logger
from UM.i18n import i18nCatalog
from cura.Settings.GlobalStack import GlobalStack
from .FirmwareUpdateCheckerJob import FirmwareUpdateCheckerJob
from UM.Settings.ContainerRegistry import ContainerRegistry
i18n_catalog = i18nCatalog("cura")
## This Extension checks for new versions of the firmware based on the latest checked version number.
# The plugin is currently only usable for applications maintained by Ultimaker. But it should be relatively easy
# to change it to work for other applications.
class FirmwareUpdateChecker(Extension):
JEDI_VERSION_URL = "http://software.ultimaker.com/jedi/releases/latest.version"
def __init__(self):
super().__init__()
# Initialize the Preference called `latest_checked_firmware` that stores the last version
# checked for the UM3. In the future if we need to check other printers' firmware
Preferences.getInstance().addPreference("info/latest_checked_firmware", "")
# Listen to a Signal that indicates a change in the list of printers, just if the user has enabled the
# 'check for updates' option
Preferences.getInstance().addPreference("info/automatic_update_check", True)
if Preferences.getInstance().getValue("info/automatic_update_check"):
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded)
def _onContainerAdded(self, container):
# Only take care when a new GlobalStack was added
if isinstance(container, GlobalStack):
Logger.log("i", "You have a '%s' in printer list. Let's check the firmware!", container.getId())
self.checkFirmwareVersion(container, True)
## Connect with software.ultimaker.com, load latest.version and check version info.
# If the version info is different from the current version, spawn a message to
# allow the user to download it.
#
# \param silent type(boolean) Suppresses messages other than "new version found" messages.
# This is used when checking for a new firmware version at startup.
def checkFirmwareVersion(self, container = None, silent = False):
job = FirmwareUpdateCheckerJob(container = container, silent = silent, url = self.JEDI_VERSION_URL)
job.start()

View File

@ -0,0 +1,86 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from UM.Preferences import Preferences
from UM.Application import Application
from UM.Message import Message
from UM.Logger import Logger
from UM.Job import Job
import urllib.request
import codecs
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QDesktopServices
from UM.i18n import i18nCatalog
i18n_catalog = i18nCatalog("cura")
## This job checks if there is an update available on the provided URL.
class FirmwareUpdateCheckerJob(Job):
def __init__(self, container = None, silent = False, url = None):
super().__init__()
self._container = container
self.silent = silent
self._url = url
self._download_url = None # If an update was found, the download_url will be set to the location of the new version.
## Callback for the message that is spawned when there is a new version.
def actionTriggered(self, message, action):
if action == "download":
if self._download_url is not None:
QDesktopServices.openUrl(QUrl(self._download_url))
def run(self):
self._download_url = None # Reset download ur.
if not self._url:
Logger.log("e", "Can not check for a new release. URL not set!")
return
try:
request = urllib.request.Request(self._url)
current_version_file = urllib.request.urlopen(request)
reader = codecs.getreader("utf-8")
# get machine name from the definition container
machine_name = self._container.definition.getName()
machine_name_parts = machine_name.lower().split(" ")
# If it is not None, then we compare between the checked_version and the current_version
# Now we just do that if the active printer is Ultimaker 3 or Ultimaker 3 Extended or any
# other Ultimaker 3 that will come in the future
if len(machine_name_parts) >= 2 and machine_name_parts[:2] == ["ultimaker", "3"]:
# Nothing to parse, just get the string
# TODO: In the future may be done by parsing a JSON file with diferent version for each printer model
current_version = reader(current_version_file).readline().rstrip()
Logger.log("i", "Reading firmware version of %s: %s", machine_name, current_version)
# If it is the first time the version is checked, the checked_version is None
checked_version = Preferences.getInstance().getValue("info/latest_checked_firmware")
# If the checked_version is '', it's because is the first time we check firmware and in this case
# we will not show the notification, but we will store it for the next time
if (checked_version != "") and (checked_version != current_version):
message = Message(i18n_catalog.i18nc("@info", "<b>New %s firmware available</b><br/><br/>To ensure that your "
"%s is equiped with the latest features it is recommended "
"to update the firmware regularly. This can be done on the "
"%s (when connected to the network) or via USB."
% (machine_name, machine_name, machine_name)))
message.addAction("download", i18n_catalog.i18nc("@action:button", "Download"), "[no_icon]", "[no_description]")
# If we do this in a cool way, the download url should be available in the JSON file
self._download_url = "https://ultimaker.com/en/resources/20500-upgrade-firmware"
message.actionTriggered.connect(self.actionTriggered)
Application.getInstance().showMessage(message)
# The first time we want to store the current version, the notification will not be shown,
# because the new version of Cura will be release before the firmware and we don't want to
# notify the user when no new firmware version is available.
Preferences.getInstance().setValue("info/latest_checked_firmware", current_version)
except Exception as e:
Logger.log("w", "Failed to check for new version: %s", e)
if not self.silent:
Message(i18n_catalog.i18nc("@info", "Could not access update information.")).show()
return

View File

@ -0,0 +1,16 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from UM.i18n import i18nCatalog
from . import FirmwareUpdateChecker
i18n_catalog = i18nCatalog("cura")
def getMetaData():
return {}
def register(app):
return {"extension": FirmwareUpdateChecker.FirmwareUpdateChecker()}

View File

@ -0,0 +1,8 @@
{
"name": "Firmware Update Checker",
"author": "Ultimaker B.V.",
"version": "1.0.0",
"description": "Checks for firmware updates.",
"api": 4,
"i18n-catalog": "cura"
}