Browse Source

Put the firmware-update meta-data in the 'normal' printer definitions and make the code handle that.

Remco Burema 6 years ago
parent
commit
2e3abbc904

+ 7 - 24
plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py

@@ -10,15 +10,12 @@ from typing import Set
 from UM.Extension import Extension
 from UM.Extension import Extension
 from UM.Application import Application
 from UM.Application import Application
 from UM.Logger import Logger
 from UM.Logger import Logger
-from UM.PluginRegistry import PluginRegistry
-from UM.Qt.QtApplication import QtApplication
 from UM.i18n import i18nCatalog
 from UM.i18n import i18nCatalog
 from UM.Settings.ContainerRegistry import ContainerRegistry
 from UM.Settings.ContainerRegistry import ContainerRegistry
 
 
 from cura.Settings.GlobalStack import GlobalStack
 from cura.Settings.GlobalStack import GlobalStack
 
 
 from .FirmwareUpdateCheckerJob import FirmwareUpdateCheckerJob
 from .FirmwareUpdateCheckerJob import FirmwareUpdateCheckerJob
-from .FirmwareUpdateCheckerLookup import FirmwareUpdateCheckerLookup, getSettingsKeyForMachine
 from .FirmwareUpdateCheckerMessage import FirmwareUpdateCheckerMessage
 from .FirmwareUpdateCheckerMessage import FirmwareUpdateCheckerMessage
 
 
 i18n_catalog = i18nCatalog("cura")
 i18n_catalog = i18nCatalog("cura")
@@ -38,18 +35,14 @@ class FirmwareUpdateChecker(Extension):
         if Application.getInstance().getPreferences().getValue("info/automatic_update_check"):
         if Application.getInstance().getPreferences().getValue("info/automatic_update_check"):
             ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded)
             ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded)
 
 
-        # Partly initialize after creation, since we need our own path from the plugin-manager.
-        self._download_url = None
         self._check_job = None
         self._check_job = None
         self._checked_printer_names = set()  # type: Set[str]
         self._checked_printer_names = set()  # type: Set[str]
-        self._lookups = None
-        QtApplication.pluginsLoaded.connect(self._onPluginsLoaded)
 
 
     ##  Callback for the message that is spawned when there is a new version.
     ##  Callback for the message that is spawned when there is a new version.
     def _onActionTriggered(self, message, action):
     def _onActionTriggered(self, message, action):
         if action == FirmwareUpdateCheckerMessage.STR_ACTION_DOWNLOAD:
         if action == FirmwareUpdateCheckerMessage.STR_ACTION_DOWNLOAD:
             machine_id = message.getMachineId()
             machine_id = message.getMachineId()
-            download_url = self._lookups.getRedirectUserFor(machine_id)
+            download_url = message.getDownloadUrl()
             if download_url is not None:
             if download_url is not None:
                 if QDesktopServices.openUrl(QUrl(download_url)):
                 if QDesktopServices.openUrl(QUrl(download_url)):
                     Logger.log("i", "Redirected browser to {0} to show newly available firmware.".format(download_url))
                     Logger.log("i", "Redirected browser to {0} to show newly available firmware.".format(download_url))
@@ -66,18 +59,6 @@ class FirmwareUpdateChecker(Extension):
     def _onJobFinished(self, *args, **kwargs):
     def _onJobFinished(self, *args, **kwargs):
         self._check_job = None
         self._check_job = None
 
 
-    def _onPluginsLoaded(self):
-        if self._lookups is not None:
-            return
-
-        self._lookups = FirmwareUpdateCheckerLookup(os.path.join(PluginRegistry.getInstance().getPluginPath(
-            "FirmwareUpdateChecker"), "resources/machines.json"))
-
-        # Initialize the Preference called `latest_checked_firmware` that stores the last version
-        # checked for each printer.
-        for machine_id in self._lookups.getMachineIds():
-            Application.getInstance().getPreferences().addPreference(getSettingsKeyForMachine(machine_id), "")
-
     ##  Connect with software.ultimaker.com, load latest.version and check version info.
     ##  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
     #   If the version info is different from the current version, spawn a message to
     #   allow the user to download it.
     #   allow the user to download it.
@@ -85,16 +66,18 @@ class FirmwareUpdateChecker(Extension):
     #   \param silent type(boolean) Suppresses messages other than "new version found" messages.
     #   \param silent type(boolean) Suppresses messages other than "new version found" messages.
     #                               This is used when checking for a new firmware version at startup.
     #                               This is used when checking for a new firmware version at startup.
     def checkFirmwareVersion(self, container = None, silent = False):
     def checkFirmwareVersion(self, container = None, silent = False):
-        if self._lookups is None:
-            self._onPluginsLoaded()
-
         container_name = container.definition.getName()
         container_name = container.definition.getName()
         if container_name in self._checked_printer_names:
         if container_name in self._checked_printer_names:
             return
             return
         self._checked_printer_names.add(container_name)
         self._checked_printer_names.add(container_name)
 
 
+        metadata = container.definition.getMetaData().get("firmware_update_info")
+        if metadata is None:
+            Logger.log("i", "No machine with name {0} in list of firmware to check.".format(container_name))
+            return
+
         self._check_job = FirmwareUpdateCheckerJob(container = container, silent = silent,
         self._check_job = FirmwareUpdateCheckerJob(container = container, silent = silent,
-                                                   lookups = self._lookups,
+                                                   machine_name = container_name, metadata = metadata,
                                                    callback = self._onActionTriggered)
                                                    callback = self._onActionTriggered)
         self._check_job.start()
         self._check_job.start()
         self._check_job.finished.connect(self._onJobFinished)
         self._check_job.finished.connect(self._onJobFinished)

+ 19 - 11
plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py

@@ -9,7 +9,7 @@ from UM.Version import Version
 
 
 import urllib.request
 import urllib.request
 from urllib.error import URLError
 from urllib.error import URLError
-from typing import Dict
+from typing import Dict, Optional
 
 
 from .FirmwareUpdateCheckerLookup import FirmwareUpdateCheckerLookup, getSettingsKeyForMachine
 from .FirmwareUpdateCheckerLookup import FirmwareUpdateCheckerLookup, getSettingsKeyForMachine
 from .FirmwareUpdateCheckerMessage import FirmwareUpdateCheckerMessage
 from .FirmwareUpdateCheckerMessage import FirmwareUpdateCheckerMessage
@@ -25,13 +25,15 @@ class FirmwareUpdateCheckerJob(Job):
     ZERO_VERSION = Version(STRING_ZERO_VERSION)
     ZERO_VERSION = Version(STRING_ZERO_VERSION)
     EPSILON_VERSION = Version(STRING_EPSILON_VERSION)
     EPSILON_VERSION = Version(STRING_EPSILON_VERSION)
 
 
-    def __init__(self, container, silent, lookups: FirmwareUpdateCheckerLookup, callback) -> None:
+    def __init__(self, container, silent, machine_name, metadata, callback) -> None:
         super().__init__()
         super().__init__()
         self._container = container
         self._container = container
         self.silent = silent
         self.silent = silent
         self._callback = callback
         self._callback = callback
 
 
-        self._lookups = lookups
+        self._machine_name = machine_name
+        self._metadata = metadata
+        self._lookups = None  # type:Optional[FirmwareUpdateCheckerLookup]
         self._headers = {}  # type:Dict[str, str]  # Don't set headers yet.
         self._headers = {}  # type:Dict[str, str]  # Don't set headers yet.
 
 
     def getUrlResponse(self, url: str) -> str:
     def getUrlResponse(self, url: str) -> str:
@@ -50,10 +52,12 @@ class FirmwareUpdateCheckerJob(Job):
         raw_str = response.split("\n", 1)[0].rstrip()
         raw_str = response.split("\n", 1)[0].rstrip()
         return Version(raw_str)
         return Version(raw_str)
 
 
-    def getCurrentVersionForMachine(self, machine_id: int) -> Version:
+    def getCurrentVersion(self) -> Version:
         max_version = self.ZERO_VERSION
         max_version = self.ZERO_VERSION
+        if self._lookups is None:
+            return max_version
 
 
-        machine_urls = self._lookups.getCheckUrlsFor(machine_id)
+        machine_urls = self._lookups.getCheckUrls()
         if machine_urls is not None:
         if machine_urls is not None:
             for url in machine_urls:
             for url in machine_urls:
                 version = self.parseVersionResponse(self.getUrlResponse(url))
                 version = self.parseVersionResponse(self.getUrlResponse(url))
@@ -61,16 +65,20 @@ class FirmwareUpdateCheckerJob(Job):
                     max_version = version
                     max_version = version
 
 
         if max_version < self.EPSILON_VERSION:
         if max_version < self.EPSILON_VERSION:
-            Logger.log("w", "MachineID {0} not handled!".format(repr(machine_id)))
+            Logger.log("w", "MachineID {0} not handled!".format(self._lookups.getMachineName()))
 
 
         return max_version
         return max_version
 
 
     def run(self):
     def run(self):
         if self._lookups is None:
         if self._lookups is None:
-            Logger.log("e", "Can not check for a new release. URL not set!")
-            return
+            self._lookups = FirmwareUpdateCheckerLookup(self._machine_name, self._metadata)
 
 
         try:
         try:
+            # Initialize a Preference that stores the last version checked for this printer.
+            Application.getInstance().getPreferences().addPreference(
+                getSettingsKeyForMachine(self._lookups.getMachineId()), "")
+
+            # Get headers
             application_name = Application.getInstance().getApplicationName()
             application_name = Application.getInstance().getApplicationName()
             application_version = Application.getInstance().getVersion()
             application_version = Application.getInstance().getVersion()
             self._headers = {"User-Agent": "%s - %s" % (application_name, application_version)}
             self._headers = {"User-Agent": "%s - %s" % (application_name, application_version)}
@@ -79,11 +87,11 @@ class FirmwareUpdateCheckerJob(Job):
             machine_name = self._container.definition.getName()
             machine_name = self._container.definition.getName()
 
 
             # If it is not None, then we compare between the checked_version and the current_version
             # If it is not None, then we compare between the checked_version and the current_version
-            machine_id = self._lookups.getMachineByName(machine_name.lower())
+            machine_id = self._lookups.getMachineId()
             if machine_id is not None:
             if machine_id is not None:
                 Logger.log("i", "You have a(n) {0} in the printer list. Let's check the firmware!".format(machine_name))
                 Logger.log("i", "You have a(n) {0} in the printer list. Let's check the firmware!".format(machine_name))
 
 
-                current_version = self.getCurrentVersionForMachine(machine_id)
+                current_version = self.getCurrentVersion()
 
 
                 # If it is the first time the version is checked, the checked_version is ""
                 # If it is the first time the version is checked, the checked_version is ""
                 setting_key_str = getSettingsKeyForMachine(machine_id)
                 setting_key_str = getSettingsKeyForMachine(machine_id)
@@ -99,7 +107,7 @@ class FirmwareUpdateCheckerJob(Job):
                 # notify the user when no new firmware version is available.
                 # notify the user when no new firmware version is available.
                 if (checked_version != "") and (checked_version != current_version):
                 if (checked_version != "") and (checked_version != current_version):
                     Logger.log("i", "SHOWING FIRMWARE UPDATE MESSAGE")
                     Logger.log("i", "SHOWING FIRMWARE UPDATE MESSAGE")
-                    message = FirmwareUpdateCheckerMessage(machine_id, machine_name)
+                    message = FirmwareUpdateCheckerMessage(machine_id, machine_name, self._lookups.getRedirectUserUrl())
                     message.actionTriggered.connect(self._callback)
                     message.actionTriggered.connect(self._callback)
                     message.show()
                     message.show()
             else:
             else:

+ 20 - 45
plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerLookup.py

@@ -1,11 +1,7 @@
 # Copyright (c) 2018 Ultimaker B.V.
 # Copyright (c) 2018 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 
-import json
-
-from typing import Callable, Dict, List, Optional
-
-from UM.Logger import Logger
+from typing import List, Optional
 
 
 from UM.i18n import i18nCatalog
 from UM.i18n import i18nCatalog
 i18n_catalog = i18nCatalog("cura")
 i18n_catalog = i18nCatalog("cura")
@@ -17,44 +13,23 @@ def getSettingsKeyForMachine(machine_id: int) -> str:
 
 
 class FirmwareUpdateCheckerLookup:
 class FirmwareUpdateCheckerLookup:
 
 
-    def __init__(self, json_path) -> None:
-        # Open the .json file with the needed lookup-lists for each machine(/model) and retrieve "raw" json.
-        with open(json_path, "r", encoding = "utf-8") as json_file:
-            machines_json = json.load(json_file).get("machines")
-        if machines_json is None:
-            Logger.log("e", "Missing or inaccessible: {0}".format(json_path))
-            return
-
+    def __init__(self, machine_name, machine_json) -> None:
         # Parse all the needed lookup-tables from the ".json" file(s) in the resources folder.
         # Parse all the needed lookup-tables from the ".json" file(s) in the resources folder.
-        self._machine_ids = []  # type:List[int]
-        self._machine_per_name = {}  # type:Dict[str, int]
-        self._parse_version_url_per_machine = {}  # type:Dict[int, Callable]
-        self._check_urls_per_machine = {}  # type:Dict[int, List[str]]
-        self._redirect_user_per_machine = {}  # type:Dict[int, str]
-        try:
-            for machine_json in machines_json:
-                machine_id = machine_json.get("id")
-                machine_name = machine_json.get("name").lower()  # Lower in case upper-case char are added to the json.
-                self._machine_ids.append(machine_id)
-                self._machine_per_name[machine_name] = machine_id
-                self._check_urls_per_machine[machine_id] = []  # Multiple check-urls: see "_comment" in the .json file.
-                for check_url in machine_json.get("check_urls"):
-                    self._check_urls_per_machine[machine_id].append(check_url)
-                self._redirect_user_per_machine[machine_id] = machine_json.get("update_url")
-        except Exception as ex:
-            Logger.log("e", "Couldn't parse firmware-update-check lookup-lists from file because {0}.".format(ex))
-
-    def getMachineIds(self) -> List[int]:
-        return self._machine_ids
-
-    def getMachineByName(self, machine_name: str) -> Optional[int]:
-        return self._machine_per_name.get(machine_name)
-
-    def getParseVersionUrlFor(self, machine_id: int) -> Optional[Callable]:
-        return self._parse_version_url_per_machine.get(machine_id)
-
-    def getCheckUrlsFor(self, machine_id: int) -> Optional[List[str]]:
-        return self._check_urls_per_machine.get(machine_id)
-
-    def getRedirectUserFor(self, machine_id: int) -> Optional[str]:
-        return self._redirect_user_per_machine.get(machine_id)
+        self._machine_id = machine_json.get("id")
+        self._machine_name = machine_name.lower()  # Lower in-case upper-case chars are added to the original json.
+        self._check_urls = []  # type:List[str]
+        for check_url in machine_json.get("check_urls"):
+            self._check_urls.append(check_url)
+        self._redirect_user = machine_json.get("update_url")
+
+    def getMachineId(self) -> Optional[int]:
+        return self._machine_id
+
+    def getMachineName(self) -> Optional[int]:
+        return self._machine_name
+
+    def getCheckUrls(self) -> Optional[List[str]]:
+        return self._check_urls
+
+    def getRedirectUserUrl(self) -> Optional[str]:
+        return self._redirect_user

+ 5 - 1
plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py

@@ -9,7 +9,7 @@ i18n_catalog = i18nCatalog("cura")
 class FirmwareUpdateCheckerMessage(Message):
 class FirmwareUpdateCheckerMessage(Message):
     STR_ACTION_DOWNLOAD = "download"
     STR_ACTION_DOWNLOAD = "download"
 
 
-    def __init__(self, machine_id: int, machine_name: str) -> None:
+    def __init__(self, machine_id: int, machine_name: str, download_url: str) -> None:
         super().__init__(i18n_catalog.i18nc(
         super().__init__(i18n_catalog.i18nc(
             "@info Don't translate {machine_name}, since it gets replaced by a printer name!",
             "@info Don't translate {machine_name}, since it gets replaced by a printer name!",
             "New features are available for your {machine_name}! It is recommended to update the firmware on your printer.").format(
             "New features are available for your {machine_name}! It is recommended to update the firmware on your printer.").format(
@@ -19,6 +19,7 @@ class FirmwareUpdateCheckerMessage(Message):
                 "New %s firmware available") % machine_name)
                 "New %s firmware available") % machine_name)
 
 
         self._machine_id = machine_id
         self._machine_id = machine_id
+        self._download_url = download_url
 
 
         self.addAction(self.STR_ACTION_DOWNLOAD,
         self.addAction(self.STR_ACTION_DOWNLOAD,
                           i18n_catalog.i18nc("@action:button", "How to update"),
                           i18n_catalog.i18nc("@action:button", "How to update"),
@@ -29,3 +30,6 @@ class FirmwareUpdateCheckerMessage(Message):
 
 
     def getMachineId(self) -> int:
     def getMachineId(self) -> int:
         return self._machine_id
         return self._machine_id
+
+    def getDownloadUrl(self) -> str:
+        return self._download_url

+ 0 - 33
plugins/FirmwareUpdateChecker/resources/machines.json

@@ -1,33 +0,0 @@
-{
-    "_comment": "There are multiple 'check_urls', because sometimes an URL is about to be phased out, and it's useful to have a new 'future-proof' one at the ready.",
-
-    "machines":
-    [
-        {
-            "id": 9066,
-            "name": "ultimaker 3",
-            "check_urls":
-            [
-                "http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources",
-                "http://software.ultimaker.com/releases/firmware/9066/stable/version.txt"
-            ],
-            "update_url": "https://ultimaker.com/en/resources/20500-upgrade-firmware"
-        },
-        {
-            "id": 9511,
-            "name": "ultimaker 3 extended",
-            "check_urls":
-            [
-                "http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources",
-                "http://software.ultimaker.com/releases/firmware/9511/stable/version.txt"
-            ],
-            "update_url": "https://ultimaker.com/en/resources/20500-upgrade-firmware"
-        },
-        {
-            "id": 9051,
-            "name": "ultimaker s5",
-            "check_urls": ["http://software.ultimaker.com/releases/firmware/9051/stable/version.txt"],
-            "update_url": "https://ultimaker.com/en/resources/20500-upgrade-firmware"
-        }
-    ]
-}

+ 10 - 1
resources/definitions/ultimaker3.def.json

@@ -24,7 +24,16 @@
         },
         },
         "first_start_actions": [ "DiscoverUM3Action" ],
         "first_start_actions": [ "DiscoverUM3Action" ],
         "supported_actions": [ "DiscoverUM3Action" ],
         "supported_actions": [ "DiscoverUM3Action" ],
-        "supports_usb_connection": false
+        "supports_usb_connection": false,
+        "firmware_update_info": {
+            "id": 9066,
+            "check_urls":
+            [
+                "http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources",
+                "http://software.ultimaker.com/releases/firmware/9066/stable/version.txt"
+            ],
+            "update_url": "https://ultimaker.com/en/resources/20500-upgrade-firmware"
+        }
     },
     },
 
 
 
 

+ 10 - 1
resources/definitions/ultimaker3_extended.def.json

@@ -23,7 +23,16 @@
             "1": "ultimaker3_extended_extruder_right"
             "1": "ultimaker3_extended_extruder_right"
         },
         },
         "first_start_actions": [ "DiscoverUM3Action" ],
         "first_start_actions": [ "DiscoverUM3Action" ],
-        "supported_actions": [ "DiscoverUM3Action" ]
+        "supported_actions": [ "DiscoverUM3Action" ],
+        "firmware_update_info": {
+            "id": 9511,
+            "check_urls":
+            [
+                "http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources",
+                "http://software.ultimaker.com/releases/firmware/9511/stable/version.txt"
+            ],
+            "update_url": "https://ultimaker.com/en/resources/20500-upgrade-firmware"
+        }
     },
     },
 
 
     "overrides": {
     "overrides": {

+ 6 - 1
resources/definitions/ultimaker_s5.def.json

@@ -30,7 +30,12 @@
         "first_start_actions": [ "DiscoverUM3Action" ],
         "first_start_actions": [ "DiscoverUM3Action" ],
         "supported_actions": [ "DiscoverUM3Action" ],
         "supported_actions": [ "DiscoverUM3Action" ],
         "supports_usb_connection": false,
         "supports_usb_connection": false,
-        "weight": -1
+        "weight": -1,
+        "firmware_update_info": {
+            "id": 9051,
+            "check_urls": ["http://software.ultimaker.com/releases/firmware/9051/stable/version.txt"],
+            "update_url": "https://ultimaker.com/en/resources/20500-upgrade-firmware"
+        }
     },
     },
 
 
     "overrides": {
     "overrides": {