From 2ba9728c78b98d91a3434627aa952cd24e0b6ffe Mon Sep 17 00:00:00 2001 From: Chamoda Pandithage Date: Sat, 6 Feb 2021 17:11:34 +0530 Subject: [PATCH 1/5] Python 3 support to save key --- octoprint_polarcloud/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/octoprint_polarcloud/__init__.py b/octoprint_polarcloud/__init__.py index 7b3b99e..512b480 100755 --- a/octoprint_polarcloud/__init__.py +++ b/octoprint_polarcloud/__init__.py @@ -311,7 +311,7 @@ def _get_keys(self): self._logger.debug('Generating key pair') key = crypto.PKey() key.generate_key(crypto.TYPE_RSA, 2048) - with open(key_filename, 'w') as f: + with open(key_filename, 'w' if sys.version_info < (3, 0) else 'wb') as f: f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key)) if sys.platform != 'win32': os.chmod(key_filename, stat.S_IRUSR | stat.S_IWUSR) From 5618421ad3e2f82961f9a7ab1aa4d85762fa42d2 Mon Sep 17 00:00:00 2001 From: Chamoda Pandithage Date: Sat, 6 Feb 2021 17:12:07 +0530 Subject: [PATCH 2/5] UI and UX improvements * Send more data to servers * Show more info after register * Ability to unregister --- octoprint_polarcloud/__init__.py | 86 +++++++++++++++++-- octoprint_polarcloud/static/js/polarcloud.js | 63 ++++++++++++-- .../templates/polarcloud_settings.jinja2 | 59 +++++++++++-- 3 files changed, 187 insertions(+), 21 deletions(-) diff --git a/octoprint_polarcloud/__init__.py b/octoprint_polarcloud/__init__.py index 512b480..e53ca10 100755 --- a/octoprint_polarcloud/__init__.py +++ b/octoprint_polarcloud/__init__.py @@ -153,6 +153,7 @@ def __init__(self): self._image_transpose = False self._printer_type = None self._disconnect_on_register = False + self._disconnect_on_unregister = False self._hello_sent = False self._port = 80 self._octoprint_client = None @@ -160,7 +161,8 @@ def __init__(self): self._next_pending = False self._print_preparer = None self._status = None - + self._email = None + self._pin = None # consider temp reads higher than this as having a target set for more # frequent reports self._set_temp_threshold = 50 @@ -172,8 +174,10 @@ def get_settings_defaults(self, *args, **kwargs): service="https://printer2.polar3d.com", service_ui="https://pc2-dev.polar3d.com", serial=None, + machine_type="Rectangular (Cartesian)", printer_type="Cartesian", email="", + pin="", max_image_size = 150000, verbose=False, upload_timelapse=True, @@ -282,6 +286,7 @@ def _create_socket(self): self._socket.on('connectPrinter', self._on_connect_printer) self._socket.on('customCommand', self._on_custom_command) self._socket.on('jogPrinter', self._on_jog_printer) + self._socket.on('unregisterResponse', self._on_unregister_response) def _start_polar_status(self): if self._polar_status_worker: @@ -294,6 +299,10 @@ def _start_polar_status(self): self._polar_status_worker.daemon = True self._polar_status_worker.start() + def _stop_polar_status(self): + if self._polar_status_worker: + self._shutdown = True + def _system(self, command_line): try: p = sarge.run(command_line, stderr=sarge.Capture()) @@ -563,7 +572,7 @@ def _wait_and_process(seconds, ignore_status_now=False): return self._logger.info("Socket disconnected, clear and restart") - if status_sent < 3 and not self._disconnect_on_register: + if status_sent < 3 and not self._disconnect_on_register and not self._disconnect_on_unregister: self._logger.warn("Unable to connect to Polar Cloud") break self._socket = None @@ -576,6 +585,10 @@ def _wait_and_process(seconds, ignore_status_now=False): def _on_disconnect(self): self._logger.debug("[Disconnected]") self._connected = False + # If unregisterd shutdown worker + if self._disconnect_on_unregister: + self._stop_polar_status() + self._disconnect_on_unregister = False #~~ time-lapse and snapshots to cloud @@ -713,6 +726,7 @@ def _hello(self): self._hello_sent = True self._status_now = True self._logger.debug('emit hello') + self._machine_type = self._settings.get(["machine_type"]) self._printer_type = self._settings.get(["printer_type"]) camUrl = self._settings.global_get(["webcam", "stream"]) try: @@ -736,6 +750,7 @@ def _hello(self): 'protocol': '2', 'camUrl': camUrl, 'transformImg': transformImg, + 'machineType': self._machine_type, 'printerType': self._printer_type }) self._challenge = None @@ -768,10 +783,15 @@ def _on_register_response(self, response, *args, **kwargs): if 'serialNumber' in response: self._serial = response['serialNumber'] self._settings.set(['serial'], self._serial) + self._settings.set(['email'], self._email) + self._settings.set(['pin'], self._pin) + self._settings.save() self._status_now = True self._plugin_manager.send_plugin_message(self._identifier, { - 'command': 'serial', - 'serial': self._serial + 'command': 'registration_success', + 'serial': self._serial, + 'email': self._email, + 'pin': self._pin, }) self._disconnect_on_register = True self._socket.disconnect() @@ -805,7 +825,7 @@ def _register(self, email, pin): if not self._socket: self._start_polar_status() - sleep(2) # give the thread a moment to start communicating + sleep(8) # give the thread a moment to start communicating self._logger.debug("Do we have a socket: {}".format(repr(self._socket))) if not self._socket: self._logger.info("Can't register because unable to communicate with Polar Cloud") @@ -819,11 +839,50 @@ def _register(self, email, pin): "publicKey": self._public_key, "myInfo": { "MAC": get_mac(), - "protocolVersion": "2" + "protocolVersion": "2", + "machineType": self._settings.get(["machine_type"]), + "printerType": self._settings.get(["printer_type"]), } }) return True + #~~ unregister -> polar: unregisterReponse + + def _on_unregister_response(self, response, *args, **kwargs): + self._logger.debug('on_unregister_response: {}'.format(repr(response))) + if response['status'] == 'SUCCESS': + self._settings.set(['serial'], '') + self._settings.set(['email'], '') + self._settings.set(['pin'], '') + self._settings.save() + self._status_now = True + self._serial = None + self._plugin_manager.send_plugin_message(self._identifier, { + 'command': 'unregistration_success', + }) + self._disconnect_on_unregister = True + self._socket.disconnect() + else: + self._plugin_manager.send_plugin_message(self._identifier, { + 'command': 'unregistration_failed', + 'reason': response['message'] + }) + + def _unregister(self): + if not self._socket: + self._start_polar_status() + sleep(8) # give the thread a moment to start communicating + self._logger.debug("Do we have a socket: {}".format(repr(self._socket))) + if not self._socket: + self._logger.info("Can't unregister because unable to communicate with Polar Cloud") + return False + + self._logger.info("emit unregister") + self._socket.emit("unregister", { + "serialNumber": self._serial, + }) + return True + #~~ cancel def _on_cancel(self, data, *args, **kwargs): @@ -1219,7 +1278,8 @@ def on_event(self, event, payload): def get_api_commands(self, *args, **kwargs): return dict( - register=[] + register=[], + unregister=[], ) def is_api_adminonly(self, *args, **kwargs): @@ -1229,14 +1289,26 @@ def on_api_command(self, command, data): status='FAIL' message='' if command == 'register' and 'email' in data and 'pin' in data: + if 'machine_type' in data: + self._settings.set(['machine_type'], data['machine_type']) if 'printer_type' in data: self._printer_type = data['printer_type'] self._settings.set(['printer_type'], self._printer_type) + if 'email' in data: + self._email = data['email'] + if 'pin' in data: + self._pin = data['pin'] if self._register(data['email'], data['pin']): status = 'WAIT' message = "Waiting for response from Polar Cloud" else: message = "Unable to communicate with Polar Cloud" + elif command == 'unregister': + if self._unregister(): + status = 'WAIT' + message = "Waiting for response from Polar Cloud" + else: + message = "Unable to communicate with Polar Cloud" else: message = "Unable to understand command" return flask.jsonify({'status': status, 'message': message}) diff --git a/octoprint_polarcloud/static/js/polarcloud.js b/octoprint_polarcloud/static/js/polarcloud.js index 84ad7ac..9ed974b 100755 --- a/octoprint_polarcloud/static/js/polarcloud.js +++ b/octoprint_polarcloud/static/js/polarcloud.js @@ -30,6 +30,10 @@ $(function() { self.registering = ko.observable(false); self.registrationFailed = ko.observable(false); self.registrationFailedReason = ko.observable(""); + self.unregistering = ko.observable(false); + self.unregistrationFailed = ko.observable(false); + self.unregistrationFailedReason = ko.observable(""); + self.machineTypes = ko.observableArray(); self.printerTypes = ko.observableArray(); self.nextPrintAvailable = ko.observable(false); @@ -40,11 +44,12 @@ $(function() { self.onBeforeBinding = function() { self.settings = self.settingsViewModel.settings.plugins.polarcloud; + self.machineTypes(["Rectangular (Cartesian)", "Circular (Delta)"]); self._ensureCurrentPrinterType(); }; self.onSettingsShown = function() { - $.ajax(self.settings.service_ui() + "/api/v1/printer_makes", { headers: "" }) + $.ajax(self.settings.service_ui() + "/api/v1/printer_makes?filter=octoprint", { headers: "" }) .done(function(response) { if ("printerMakes" in response) { self.printerTypes(response["printerMakes"]); @@ -60,15 +65,17 @@ $(function() { }); }; - self.showRegistration = function() { - self.emailAddress(self.settings.email()); - $("#plugin_polarcloud_registration").modal("show"); + self.changeRegistrationStatus = function() { + if(self.settings.serial()){ + $("#plugin_polarcloud_unregistration").modal("show"); + } else { + $("#plugin_polarcloud_registration").modal("show"); + } }; self.registerPrinter = function() { if (self.registering()) return; - self.settings.email(self.emailAddress()) self.registering(true); self.registrationFailed(false); setTimeout(function() { @@ -81,12 +88,32 @@ $(function() { OctoPrint.simpleApiCommand("polarcloud", "register", { "email": self.emailAddress(), "pin": self.pin(), - "printer_type": self.settings.printer_type() + "printer_type": self.settings.printer_type(), + "machine_type": self.settings.machine_type() }).done(function(response) { console.log("polarcloud register response" + JSON.stringify(response)); }); }; + self.unregisterPrinter = function() { + if (self.unregistering()) + return; + self.unregistering(true); + self.unregistrationFailed(false); + setTimeout(function() { + if (self.unregistering()) { + self.unregistering(false); + self.unregistrationFailed(true); + self.unregistrationFailedReason("Couldn't connect to the Polar Cloud."); + } + }, 10000); + OctoPrint.simpleApiCommand("polarcloud", "unregister", { + "serialNumber": "test", + }).done(function(response) { + console.log("polarcloud unregister response" + JSON.stringify(response)); + }); + } + self.onDataUpdaterPluginMessage = function(plugin, data) { if (plugin != "polarcloud") return; @@ -98,11 +125,29 @@ $(function() { return; } - if (data.command == "serial" && data.serial) { + if (data.command == "registration_success") { self.settings.serial(data.serial); + self.settings.email(data.email); + self.settings.pin(data.pin); + self.registering(false); + $("#plugin_polarcloud_registration").modal("hide"); + return + } + + if (data.command == "unregistration_failed") { + self.unregistering(false); + self.unregistrationFailed(true); + self.unregistrationFailedReason(data.reason); + return; + } + + if (data.command == "unregistration_success") { + self.unregistering(false); + self.settings.serial(''); + self.settings.email(''); + self.settings.pin(''); + $("#plugin_polarcloud_unregistration").modal("hide"); } - self.registering(false); - $("#plugin_polarcloud_registration").modal("hide"); }; } diff --git a/octoprint_polarcloud/templates/polarcloud_settings.jinja2 b/octoprint_polarcloud/templates/polarcloud_settings.jinja2 index 90f9180..1e1b874 100644 --- a/octoprint_polarcloud/templates/polarcloud_settings.jinja2 +++ b/octoprint_polarcloud/templates/polarcloud_settings.jinja2 @@ -1,7 +1,7 @@
+
From 944358b4b8db63b4a0d46434ae3bdca7ec070a2a Mon Sep 17 00:00:00 2001 From: Chamoda Pandithage Date: Wed, 10 Feb 2021 22:40:19 +0530 Subject: [PATCH 3/5] Allow users to change next_print without printer capability --- octoprint_polarcloud/__init__.py | 4 ++-- octoprint_polarcloud/static/js/polarcloud.js | 8 -------- octoprint_polarcloud/templates/polarcloud_settings.jinja2 | 4 ++-- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/octoprint_polarcloud/__init__.py b/octoprint_polarcloud/__init__.py index e53ca10..fd818fd 100755 --- a/octoprint_polarcloud/__init__.py +++ b/octoprint_polarcloud/__init__.py @@ -182,7 +182,7 @@ def get_settings_defaults(self, *args, **kwargs): verbose=False, upload_timelapse=True, enable_system_commands=True, - next_print=True + next_print=False ) def _update_local_settings(self): @@ -770,7 +770,7 @@ def _send_capabilities(self): }) def _send_next_print(self): - if self._capabilities and 'sendNextPrint' in self._capabilities and self._settings.get_boolean(['next_print']): + if self._settings.get_boolean(['next_print']): self._logger.debug("emit sendNextPrint") self._socket.emit('sendNextPrint', { 'serialNumber': self._serial diff --git a/octoprint_polarcloud/static/js/polarcloud.js b/octoprint_polarcloud/static/js/polarcloud.js index 9ed974b..07f9e03 100755 --- a/octoprint_polarcloud/static/js/polarcloud.js +++ b/octoprint_polarcloud/static/js/polarcloud.js @@ -35,7 +35,6 @@ $(function() { self.unregistrationFailedReason = ko.observable(""); self.machineTypes = ko.observableArray(); self.printerTypes = ko.observableArray(); - self.nextPrintAvailable = ko.observable(false); self._ensureCurrentPrinterType = function() { if (self.printerTypes().indexOf(self.settings.printer_type()) < 0) @@ -56,13 +55,6 @@ $(function() { self._ensureCurrentPrinterType(); } }); - self.nextPrintAvailable(false); - OctoPrint.simpleApiGet("polarcloud") - .done(function(response) { - if ("capabilities" in response && response["capabilities"].indexOf("sendNextPrint") >= 0) { - self.nextPrintAvailable(true); - } - }); }; self.changeRegistrationStatus = function() { diff --git a/octoprint_polarcloud/templates/polarcloud_settings.jinja2 b/octoprint_polarcloud/templates/polarcloud_settings.jinja2 index 1e1b874..60ab820 100644 --- a/octoprint_polarcloud/templates/polarcloud_settings.jinja2 +++ b/octoprint_polarcloud/templates/polarcloud_settings.jinja2 @@ -84,10 +84,10 @@ -
+
From b6d60dcfb74597c14e0e850b5211b6bbb3aa7eca Mon Sep 17 00:00:00 2001 From: Chamoda Pandithage Date: Fri, 26 Feb 2021 19:04:41 +0530 Subject: [PATCH 4/5] Ablity to load printer types dynamically --- octoprint_polarcloud/__init__.py | 2 +- octoprint_polarcloud/static/js/polarcloud.js | 59 ++++++++++++++++--- .../templates/polarcloud_settings.jinja2 | 6 +- 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/octoprint_polarcloud/__init__.py b/octoprint_polarcloud/__init__.py index 9f9ec2a..def5a01 100755 --- a/octoprint_polarcloud/__init__.py +++ b/octoprint_polarcloud/__init__.py @@ -174,7 +174,7 @@ def get_settings_defaults(self, *args, **kwargs): service="https://printer2.polar3d.com", service_ui="https://pc2-dev.polar3d.com", serial=None, - machine_type="Rectangular (Cartesian)", + machine_type="Cartesian", printer_type="Cartesian", email="", pin="", diff --git a/octoprint_polarcloud/static/js/polarcloud.js b/octoprint_polarcloud/static/js/polarcloud.js index 07f9e03..444d733 100755 --- a/octoprint_polarcloud/static/js/polarcloud.js +++ b/octoprint_polarcloud/static/js/polarcloud.js @@ -35,28 +35,69 @@ $(function() { self.unregistrationFailedReason = ko.observable(""); self.machineTypes = ko.observableArray(); self.printerTypes = ko.observableArray(); + self.isPrinterTypesLoading = ko.observable(false); + self.machineType = ko.observable(""); + self.printerType = ko.observable(""); - self._ensureCurrentPrinterType = function() { - if (self.printerTypes().indexOf(self.settings.printer_type()) < 0) - self.printerTypes.push(self.settings.printer_type()); - }; + self.machineType.subscribe(function (value) { + if (value) { + self.settings.machine_type(value); + } + }); + + self.printerType.subscribe(function (value) { + if (value) { + self.settings.printer_type(value); + } + }); self.onBeforeBinding = function() { self.settings = self.settingsViewModel.settings.plugins.polarcloud; - self.machineTypes(["Rectangular (Cartesian)", "Circular (Delta)"]); - self._ensureCurrentPrinterType(); }; + self.printerTypeOptionsValue = function(item) { + return item == "Other/Custom" ? self.settings.machine_type() : item; + } + + self.printerTypeOptionsText = function(item) { + return item; + } + + self.loadPrinterTypes = function(machine_type, printer_type) { + self.isPrinterTypesLoading(true); + $.ajax(self.settings.service_ui() + "/api/v1/printer_makes?filter=" + machine_type.toLocaleLowerCase(), { headers: "" }) + .done(function(response) { + if ("printerMakes" in response) { + self.isPrinterTypesLoading(false); + var options = response["printerMakes"]; + options.push("Other/Custom"); + self.printerTypes(options); + if (printer_type) { + self.printerType(printer_type); + } + } + }); + } + self.onSettingsShown = function() { - $.ajax(self.settings.service_ui() + "/api/v1/printer_makes?filter=octoprint", { headers: "" }) + var initialMachineType = self.settings.machine_type(); + var initialPrinterType = self.settings.printer_type(); + $.ajax(self.settings.service_ui() + "/api/v1/printer_makes?filter=octoprint-build", { headers: "" }) .done(function(response) { if ("printerMakes" in response) { - self.printerTypes(response["printerMakes"]); - self._ensureCurrentPrinterType(); + self.machineTypes(response["printerMakes"]); + self.machineType(initialMachineType); + self.loadPrinterTypes(initialMachineType, initialPrinterType); } }); }; + self.onChangeMachineType = function(obj, event) { + if (event.originalEvent) { + self.loadPrinterTypes(self.machineType(), null); + } + } + self.changeRegistrationStatus = function() { if(self.settings.serial()){ $("#plugin_polarcloud_unregistration").modal("show"); diff --git a/octoprint_polarcloud/templates/polarcloud_settings.jinja2 b/octoprint_polarcloud/templates/polarcloud_settings.jinja2 index 60ab820..485514b 100644 --- a/octoprint_polarcloud/templates/polarcloud_settings.jinja2 +++ b/octoprint_polarcloud/templates/polarcloud_settings.jinja2 @@ -35,13 +35,13 @@
- +
- +
- +
** Any changes made requires a restart to take effect **
From c8fb0b2a39e5020b690063e84ad3a39b35c0b6f8 Mon Sep 17 00:00:00 2001 From: Chamoda Pandithage Date: Wed, 3 Mar 2021 11:08:43 +0530 Subject: [PATCH 5/5] Fix spelling not -> note --- octoprint_polarcloud/templates/polarcloud_settings.jinja2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/octoprint_polarcloud/templates/polarcloud_settings.jinja2 b/octoprint_polarcloud/templates/polarcloud_settings.jinja2 index 485514b..87e0435 100644 --- a/octoprint_polarcloud/templates/polarcloud_settings.jinja2 +++ b/octoprint_polarcloud/templates/polarcloud_settings.jinja2 @@ -147,7 +147,7 @@ {{ _('Are you sure you want to unregister this printer? This will mark your serial number as "Deleted" in the cloud and allow someone else to register this octoprint instance with their own username and PIN.') }}

- {{ _('Please not that if you try to register it again using your same credentials, you will be granted the same serial number you had before.') }} + {{ _('Please note that if you try to register it again using your same credentials, you will be granted the same serial number you had before.') }}