-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0283ed2
Showing
17 changed files
with
1,536 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# This file is for unifying the coding style for different editors and IDEs | ||
# editorconfig.org | ||
|
||
root = true | ||
|
||
[*] | ||
end_of_line = lf | ||
charset = utf-8 | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true | ||
|
||
[**.py] | ||
indent_style = space | ||
indent_size = 4 | ||
|
||
[**.js] | ||
indent_style = space | ||
indent_size = 4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
*.pyc | ||
*.swp | ||
.idea | ||
*.iml | ||
build | ||
dist | ||
*.egg* | ||
.DS_Store | ||
*.zip | ||
extras |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
include README.md | ||
recursive-include octoprint_bambu_printer/templates * | ||
recursive-include octoprint_bambu_printer/translations * | ||
recursive-include octoprint_bambu_printer/static * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# OctoPrint-BambuPrinter | ||
|
||
**TODO:** Describe what your plugin does. | ||
|
||
## Setup | ||
|
||
Install via the bundled [Plugin Manager](https://docs.octoprint.org/en/master/bundledplugins/pluginmanager.html) | ||
or manually using this URL: | ||
|
||
https://github.com/jneilliii/OctoPrint-BambuPrinter/archive/master.zip | ||
|
||
**TODO:** Describe how to install your plugin, if more needs to be done than just installing it via pip or through | ||
the plugin manager. | ||
|
||
## Configuration | ||
|
||
**TODO:** Describe your plugin's configuration options (if any). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[python: */**.py] | ||
|
||
[jinja2: */**.jinja2] | ||
silent=false | ||
extensions=jinja2.ext.do, octoprint.util.jinja.trycatch | ||
|
||
[javascript: */**.js] | ||
extract_messages = gettext, ngettext |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
# coding=utf-8 | ||
from __future__ import absolute_import | ||
|
||
import threading | ||
import time | ||
|
||
import octoprint.plugin | ||
|
||
from .ftpsclient import IoTFTPSClient | ||
|
||
|
||
class BambuPrintPlugin( | ||
octoprint.plugin.SettingsPlugin, octoprint.plugin.TemplatePlugin | ||
): | ||
|
||
def get_template_configs(self): | ||
return [{"type": "settings", "custom_bindings": False}] | ||
|
||
def get_settings_defaults(self): | ||
return {"device_type": "X1C", | ||
"serial": "", | ||
"host": "", | ||
"access_code": "", | ||
"username": "bblp", | ||
"timelapse": False, | ||
"bed_leveling": True, | ||
"flow_cali": False, | ||
"vibration_cali": True, | ||
"layer_inspect": True, | ||
"use_ams": False} | ||
|
||
def support_3mf_files(self): | ||
return {'machinecode': {'3mf': ["3mf"]}} | ||
|
||
def upload_to_sd(self, printer, filename, path, sd_upload_started, sd_upload_succeeded, sd_upload_failed, *args, **kwargs): | ||
self._logger.debug(f"Starting upload from {filename} to {filename}") | ||
sd_upload_started(filename, filename) | ||
def process(): | ||
host = self._settings.get(["host"]) | ||
access_code = self._settings.get(["access_code"]) | ||
elapsed = time.monotonic() | ||
|
||
try: | ||
ftp = IoTFTPSClient(f"{host}", 990, "bblp", f"{access_code}", ssl_implicit=True) | ||
if ftp.upload_file(path, f"{filename}"): | ||
elapsed = time.monotonic() - elapsed | ||
sd_upload_succeeded(filename, filename, elapsed) | ||
# remove local file after successful upload to Bambu | ||
self._file_manager.remove_file("local", filename) | ||
else: | ||
raise Exception("upload failed") | ||
except Exception as e: | ||
elapsed = time.monotonic() - elapsed | ||
sd_upload_failed(filename, filename, elapsed) | ||
self._logger.debug(f"Error uploading file {filename}") | ||
|
||
thread = threading.Thread(target=process) | ||
thread.daemon = True | ||
thread.start() | ||
|
||
return filename | ||
|
||
def virtual_printer_factory(self, comm_instance, port, baudrate, read_timeout): | ||
if not port == "BAMBU": | ||
return None | ||
|
||
if self._settings.get(["serial"]) == "" or self._settings.get(["host"]) == "" or self._settings.get(["access_code"]) == "": | ||
return None | ||
|
||
import logging.handlers | ||
|
||
from octoprint.logging.handlers import CleaningTimedRotatingFileHandler | ||
|
||
seriallog_handler = CleaningTimedRotatingFileHandler( | ||
self._settings.get_plugin_logfile_path(postfix="serial"), | ||
when="D", | ||
backupCount=3, | ||
) | ||
seriallog_handler.setFormatter(logging.Formatter("%(asctime)s %(message)s")) | ||
seriallog_handler.setLevel(logging.DEBUG) | ||
|
||
from . import virtual | ||
|
||
serial_obj = virtual.BambuPrinter( | ||
self._settings, | ||
self._printer_profile_manager, | ||
data_folder=self.get_plugin_data_folder(), | ||
seriallog_handler=seriallog_handler, | ||
read_timeout=float(read_timeout), | ||
faked_baudrate=baudrate, | ||
) | ||
return serial_obj | ||
|
||
def get_additional_port_names(self, *args, **kwargs): | ||
if self._settings.get(["serial"]) != "" and self._settings.get(["host"]) != "" and self._settings.get(["access_code"]) != "": | ||
return ["BAMBU"] | ||
else: | ||
return [] | ||
|
||
def get_update_information(self): | ||
return {'bambu_printer': {'displayName': "Bambu Printer", | ||
'displayVersion': self._plugin_version, | ||
'type': "github_release", | ||
'user': "jneilliii", | ||
'repo': "OctoPrint-BambuPrinter", | ||
'current': self._plugin_version, | ||
'stable_branch': {'name': "Stable", | ||
'branch': "master", | ||
'comittish': ["master"]}, | ||
'prerelease_branches': [ | ||
{'name': "Release Candidate", | ||
'branch': "rc", | ||
'comittish': ["rc", "master"]} | ||
], | ||
'pip': "https://github.com/jneilliii/OctoPrint-BambuPrinter/archive/{target_version}.zip"}} | ||
|
||
|
||
__plugin_name__ = "Bambu Printer" | ||
__plugin_pythoncompat__ = ">=3.7,<4" | ||
|
||
|
||
def __plugin_load__(): | ||
plugin = BambuPrintPlugin() | ||
|
||
global __plugin_implementation__ | ||
__plugin_implementation__ = plugin | ||
|
||
global __plugin_hooks__ | ||
__plugin_hooks__ = { | ||
"octoprint.comm.transport.serial.factory": __plugin_implementation__.virtual_printer_factory, | ||
"octoprint.comm.transport.serial.additional_port_names": __plugin_implementation__.get_additional_port_names, | ||
"octoprint.filemanager.extension_tree": __plugin_implementation__.support_3mf_files, | ||
"octoprint.printer.sdcardupload": __plugin_implementation__.upload_to_sd, | ||
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from ._client import IoTFTPSClient | ||
from ._version import __version__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
"""wrapper for FTPS server interactions""" | ||
|
||
import ftplib | ||
import ssl | ||
from typing import List, Optional, Union | ||
|
||
|
||
class ImplicitTLS(ftplib.FTP_TLS): | ||
"""ftplib.FTP_TLS sub-class to support implicit SSL FTPS""" | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
self._sock = None | ||
|
||
@property | ||
def sock(self): | ||
"""return socket""" | ||
return self._sock | ||
|
||
@sock.setter | ||
def sock(self, value): | ||
"""wrap and set SSL socket""" | ||
if value is not None and not isinstance(value, ssl.SSLSocket): | ||
value = self.context.wrap_socket(value) | ||
self._sock = value | ||
|
||
def ntransfercmd(self, cmd, rest=None): | ||
conn, size = ftplib.FTP.ntransfercmd(self, cmd, rest) | ||
if self._prot_p: | ||
conn = self.context.wrap_socket(conn, | ||
server_hostname=self.host, | ||
session=self.sock.session) # this is the fix | ||
return conn, size | ||
|
||
|
||
class IoTFTPSClient: | ||
"""iot ftps ftpsclient""" | ||
|
||
ftps_host: str | ||
ftps_port: int | ||
ftps_user: str | ||
ftps_pass: str | ||
ssl_implicit: bool | ||
ftps_session: Union[ftplib.FTP, ImplicitTLS] | ||
|
||
def __init__( | ||
self, | ||
ftps_host: str, | ||
ftps_port: Optional[int] = 21, | ||
ftps_user: Optional[str] = "", | ||
ftps_pass: Optional[str] = "", | ||
ssl_implicit: Optional[bool] = False, | ||
) -> None: | ||
self.ftps_host = ftps_host | ||
self.ftps_port = ftps_port | ||
self.ftps_user = ftps_user | ||
self.ftps_pass = ftps_pass | ||
self.ssl_implicit = ssl_implicit | ||
self.instantiate_ftps_session() | ||
|
||
def __repr__(self) -> str: | ||
return ( | ||
"IoT FTPS Client\n" | ||
"--------------------\n" | ||
f"host: {self.ftps_host}\n" | ||
f"port: {self.ftps_port}\n" | ||
f"user: {self.ftps_user}\n" | ||
f"ssl: {self.ssl_implicit}" | ||
) | ||
|
||
def instantiate_ftps_session(self) -> None: | ||
"""init ftps_session based on input params""" | ||
try: | ||
if self.ssl_implicit: | ||
self.ftps_session = ImplicitTLS() | ||
else: | ||
self.ftps_session = ftplib.FTP() | ||
|
||
self.ftps_session.connect(host=self.ftps_host, port=self.ftps_port) | ||
|
||
if self.ftps_user != "" and self.ftps_pass != "": | ||
self.ftps_session.login(user=self.ftps_user, passwd=self.ftps_pass) | ||
else: | ||
self.ftps_session.login() | ||
|
||
if self.ssl_implicit: | ||
self.ftps_session.prot_p() | ||
|
||
except Exception as ex: | ||
print(f"unexpected exception occurred: {ex}") | ||
pass | ||
return | ||
|
||
def disconnect(self) -> None: | ||
"""disconnect the current session from the ftps server""" | ||
try: | ||
self.ftps_session.close() | ||
except Exception as ex: | ||
print(f"unexpected exception occurred: {ex}") | ||
pass | ||
return | ||
|
||
def download_file(self, source: str, dest: str) -> bool: | ||
"""download a file to a path on the local filesystem""" | ||
try: | ||
with open(dest, "wb") as file: | ||
self.ftps_session.retrbinary(f"RETR {source}", file.write) | ||
return True | ||
except Exception as ex: | ||
print(f"unexpected exception occurred: {ex}") | ||
pass | ||
return False | ||
|
||
def upload_file(self, source: str, dest: str) -> bool: | ||
"""upload a file to a path inside the FTPS server""" | ||
try: | ||
with open(source, "rb") as file: | ||
self.ftps_session.storbinary(f"STOR {dest}", file) | ||
return True | ||
except Exception as ex: | ||
print(f"unexpected exception occurred: {ex}") | ||
pass | ||
return False | ||
|
||
def delete_file(self, path: str) -> bool: | ||
"""delete a file from under a path inside the FTPS server""" | ||
try: | ||
self.ftps_session.delete(path) | ||
return True | ||
except Exception as ex: | ||
print(f"unexpected exception occurred: {ex}") | ||
pass | ||
return False | ||
|
||
def move_file(self, source: str, dest: str) -> bool: | ||
"""move a file inside the FTPS server to another path inside the FTPS server""" | ||
try: | ||
self.ftps_session.rename(source, dest) | ||
return True | ||
except Exception as ex: | ||
print(f"unexpected exception occurred: {ex}") | ||
pass | ||
return False | ||
|
||
def list_files( | ||
self, path: str, file_pattern: Optional[str] = None | ||
) -> Union[List[str], None]: | ||
"""list files under a path inside the FTPS server""" | ||
try: | ||
files = self.ftps_session.nlst(path) | ||
if not files: | ||
return | ||
if file_pattern: | ||
return [f for f in files if file_pattern in f] | ||
return files | ||
except Exception as ex: | ||
print(f"unexpected exception occurred: {ex}") | ||
pass | ||
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
VERSION = "1.1.1" | ||
|
||
__version__ = VERSION |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* View model for OctoPrint-BambuPrinter | ||
* | ||
* Author: jneilliii | ||
* License: AGPLv3 | ||
*/ | ||
$(function() { | ||
function Bambu_printerViewModel(parameters) { | ||
var self = this; | ||
|
||
// assign the injected parameters, e.g.: | ||
// self.loginStateViewModel = parameters[0]; | ||
// self.settingsViewModel = parameters[1]; | ||
|
||
// TODO: Implement your plugin's view model here. | ||
} | ||
|
||
/* view model class, parameters for constructor, container to bind to | ||
* Please see http://docs.octoprint.org/en/master/plugins/viewmodels.html#registering-custom-viewmodels for more details | ||
* and a full list of the available options. | ||
*/ | ||
OCTOPRINT_VIEWMODELS.push({ | ||
construct: Bambu_printerViewModel, | ||
// ViewModels your plugin depends on, e.g. loginStateViewModel, settingsViewModel, ... | ||
dependencies: [ /* "loginStateViewModel", "settingsViewModel" */ ], | ||
// Elements to bind to, e.g. #settings_plugin_bambu_printer, #tab_plugin_bambu_printer, ... | ||
elements: [ /* ... */ ] | ||
}); | ||
}); |
Oops, something went wrong.