Compare commits

...

8 Commits

Author SHA1 Message Date
e1ea88dbae 0.0.22
* add file listing of avi files for non X1 devices, #29
2024-05-24 19:37:51 -04:00
ac7bb16a2b 0.0.21
add timelapses with thumbnail
2024-05-18 18:45:05 -04:00
112210a3f1 list timelapses on printer with thumbnail and download button 2024-05-18 14:31:03 -04:00
176154cfee 0.0.20 (#27)
* fixes issue related to printing a cloud print again and subtask_name including full path to file, #25
2024-05-14 13:33:37 -04:00
56e5fb4dd2 fixes issue related to printing a cloud print again and subtask_name including full path to file, #25 2024-05-12 17:21:53 -04:00
3e7708429d 0.0.19 (#24)
* attempt to fix A1 related print issues, #9 
* flow rate increase logic for M220 from x1plus community
2024-05-12 13:39:25 -04:00
908173214f adjust start print command for better A1 compatibility 2024-03-17 00:34:42 -04:00
df4bd6cf44 additional logging 2024-03-08 22:30:39 -05:00
5 changed files with 299 additions and 18 deletions

View File

@ -1,12 +1,19 @@
# coding=utf-8 # coding=utf-8
from __future__ import absolute_import from __future__ import absolute_import
import os
import threading import threading
import time import time
import flask
import datetime
import octoprint.plugin import octoprint.plugin
from octoprint.events import Events from octoprint.events import Events
from octoprint.util import get_formatted_size, get_formatted_datetime, is_hidden_path
from octoprint.server.util.flask import no_firstrun_access
from octoprint.server.util.tornado import LargeResponseHandler, UrlProxyHandler, path_validation_factory
from octoprint.access.permissions import Permissions
from urllib.parse import quote as urlquote
from .ftpsclient import IoTFTPSClient from .ftpsclient import IoTFTPSClient
@ -14,13 +21,15 @@ class BambuPrintPlugin(octoprint.plugin.SettingsPlugin,
octoprint.plugin.TemplatePlugin, octoprint.plugin.TemplatePlugin,
octoprint.plugin.AssetPlugin, octoprint.plugin.AssetPlugin,
octoprint.plugin.EventHandlerPlugin, octoprint.plugin.EventHandlerPlugin,
octoprint.plugin.SimpleApiPlugin): octoprint.plugin.SimpleApiPlugin,
octoprint.plugin.BlueprintPlugin):
def get_assets(self): def get_assets(self):
return {'js': ["js/bambu_printer.js"]} return {'js': ["js/bambu_printer.js"]}
def get_template_configs(self): def get_template_configs(self):
return [{"type": "settings", "custom_bindings": True}] #, {"type": "generic", "custom_bindings": True, "template": "bambu_printer.jinja2"}] return [{"type": "settings", "custom_bindings": True},
{"type": "generic", "custom_bindings": True, "template": "bambu_timelapse.jinja2"}] #, {"type": "generic", "custom_bindings": True, "template": "bambu_printer.jinja2"}]
def get_settings_defaults(self): def get_settings_defaults(self):
return {"device_type": "X1C", return {"device_type": "X1C",
@ -47,7 +56,6 @@ class BambuPrintPlugin(octoprint.plugin.SettingsPlugin,
def get_api_commands(self): def get_api_commands(self):
return {"register": ["email", "password", "region", "auth_token"]} return {"register": ["email", "password", "region", "auth_token"]}
def on_api_command(self, command, data): def on_api_command(self, command, data):
import flask
if command == "register": if command == "register":
if "email" in data and "password" in data and "region" in data and "auth_token" in data: if "email" in data and "password" in data and "region" in data and "auth_token" in data:
self._logger.info(f"Registering user {data['email']}") self._logger.info(f"Registering user {data['email']}")
@ -129,6 +137,103 @@ class BambuPrintPlugin(octoprint.plugin.SettingsPlugin,
else: else:
return [] return []
def get_timelapse_file_list(self):
if flask.request.path.startswith('/api/timelapse'):
def process():
host = self._settings.get(["host"])
access_code = self._settings.get(["access_code"])
return_file_list = []
try:
ftp = IoTFTPSClient(f"{host}", 990, "bblp", f"{access_code}", ssl_implicit=True)
if self._settings.get(["device_type"]) in ["X1", "X1C"]:
timelapse_file_list = ftp.list_files("timelapse/", ".mp4") or []
else:
timelapse_file_list = ftp.list_files("timelapse/", ".avi") or []
for entry in timelapse_file_list:
if entry.startswith("/"):
filename = entry[1:].replace("timelapse/", "")
else:
filename = entry.replace("timelapse/", "")
filesize = ftp.ftps_session.size(f"timelapse/{filename}")
date_str = ftp.ftps_session.sendcmd(f"MDTM timelapse/{filename}").replace("213 ", "")
filedate = datetime.datetime.strptime(date_str, "%Y%m%d%H%M%S").replace(tzinfo=datetime.timezone.utc).timestamp()
return_file_list.append(
{
"bytes": filesize,
"date": get_formatted_datetime(datetime.datetime.fromtimestamp(filedate)),
"name": filename,
"size": get_formatted_size(filesize),
"thumbnail": "/plugin/bambu_printer/thumbnail/" + filename.replace(".mp4", ".jpg"),
"timestamp": filedate,
"url": f"/plugin/bambu_printer/timelapse/{filename}"
})
self._plugin_manager.send_plugin_message(self._identifier, {'files': return_file_list})
except Exception as e:
self._logger.debug(f"Error getting timelapse files: {e}")
thread = threading.Thread(target=process)
thread.daemon = True
thread.start()
def _hook_octoprint_server_api_before_request(self, *args, **kwargs):
return [self.get_timelapse_file_list]
@octoprint.plugin.BlueprintPlugin.route("/timelapse/<filename>", methods=["GET"])
@octoprint.server.util.flask.restricted_access
@no_firstrun_access
@Permissions.TIMELAPSE_DOWNLOAD.require(403)
def downloadTimelapse(self, filename):
dest_filename = os.path.join(self.get_plugin_data_folder(), filename)
host = self._settings.get(["host"])
access_code = self._settings.get(["access_code"])
if not os.path.exists(dest_filename):
ftp = IoTFTPSClient(f"{host}", 990, "bblp", f"{access_code}", ssl_implicit=True)
download_result = ftp.download_file(
source=f"timelapse/{filename}",
dest=dest_filename,
)
return flask.redirect("/plugin/bambu_printer/download/timelapse/" + urlquote(filename), code=302)
@octoprint.plugin.BlueprintPlugin.route("/thumbnail/<filename>", methods=["GET"])
@octoprint.server.util.flask.restricted_access
@no_firstrun_access
@Permissions.TIMELAPSE_DOWNLOAD.require(403)
def downloadThumbnail(self, filename):
dest_filename = os.path.join(self.get_plugin_data_folder(), filename)
host = self._settings.get(["host"])
access_code = self._settings.get(["access_code"])
if not os.path.exists(dest_filename):
ftp = IoTFTPSClient(f"{host}", 990, "bblp", f"{access_code}", ssl_implicit=True)
download_result = ftp.download_file(
source=f"timelapse/thumbnail/{filename}",
dest=dest_filename,
)
return flask.redirect("/plugin/bambu_printer/download/thumbnail/" + urlquote(filename), code=302)
def is_blueprint_csrf_protected(self):
return True
def route_hook(self, server_routes, *args, **kwargs):
return [
(r"/download/timelapse/(.*)", LargeResponseHandler,
{'path': self.get_plugin_data_folder(), 'as_attachment': True, 'path_validation': path_validation_factory(
lambda path: not is_hidden_path(path), status_code=404)}),
(r"/download/thumbnail/(.*)", LargeResponseHandler,
{'path': self.get_plugin_data_folder(), 'as_attachment': True, 'path_validation': path_validation_factory(
lambda path: not is_hidden_path(path), status_code=404)})
]
def get_update_information(self): def get_update_information(self):
return {'bambu_printer': {'displayName': "Bambu Printer", return {'bambu_printer': {'displayName': "Bambu Printer",
'displayVersion': self._plugin_version, 'displayVersion': self._plugin_version,
@ -164,4 +269,6 @@ def __plugin_load__():
"octoprint.filemanager.extension_tree": __plugin_implementation__.support_3mf_files, "octoprint.filemanager.extension_tree": __plugin_implementation__.support_3mf_files,
"octoprint.printer.sdcardupload": __plugin_implementation__.upload_to_sd, "octoprint.printer.sdcardupload": __plugin_implementation__.upload_to_sd,
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information, "octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information,
"octoprint.server.api.before_request": __plugin_implementation__._hook_octoprint_server_api_before_request,
"octoprint.server.http.routes": __plugin_implementation__.route_hook
} }

View File

@ -11,6 +11,9 @@ $(function () {
self.settingsViewModel = parameters[0]; self.settingsViewModel = parameters[0];
self.filesViewModel = parameters[1]; self.filesViewModel = parameters[1];
self.loginStateViewModel = parameters[2];
self.accessViewModel = parameters[3];
self.timelapseViewModel = parameters[4];
self.getAuthToken = function (data) { self.getAuthToken = function (data) {
self.settingsViewModel.settings.plugins.bambu_printer.auth_token(""); self.settingsViewModel.settings.plugins.bambu_printer.auth_token("");
@ -27,6 +30,59 @@ $(function () {
}); });
}; };
// initialize list helper
self.listHelper = new ItemListHelper(
"timelapseFiles",
{
name: function (a, b) {
// sorts ascending
if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase())
return -1;
if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase())
return 1;
return 0;
},
date: function (a, b) {
// sorts descending
if (a["date"] > b["date"]) return -1;
if (a["date"] < b["date"]) return 1;
return 0;
},
size: function (a, b) {
// sorts descending
if (a["bytes"] > b["bytes"]) return -1;
if (a["bytes"] < b["bytes"]) return 1;
return 0;
}
},
{},
"name",
[],
[],
CONFIG_TIMELAPSEFILESPERPAGE
);
self.onDataUpdaterPluginMessage = function(plugin, data) {
if (plugin != "bambu_printer") {
return;
}
if (data.files !== undefined) {
console.log(data.files);
self.listHelper.updateItems(data.files);
self.listHelper.resetPage();
}
};
self.onBeforeBinding = function () {
$('#bambu_timelapse').appendTo("#timelapse");
};
self.showTimelapseThumbnail = function(data) {
$("#bambu_printer_timelapse_thumbnail").attr("src", data.thumbnail);
$("#bambu_printer_timelapse_preview").modal('show');
};
/*$('#files div.upload-buttons > span.fileinput-button:first, #files div.folder-button').remove(); /*$('#files div.upload-buttons > span.fileinput-button:first, #files div.folder-button').remove();
$('#files div.upload-buttons > span.fileinput-button:first').removeClass('span6').addClass('input-block-level'); $('#files div.upload-buttons > span.fileinput-button:first').removeClass('span6').addClass('input-block-level');
@ -85,8 +141,8 @@ $(function () {
OCTOPRINT_VIEWMODELS.push({ OCTOPRINT_VIEWMODELS.push({
construct: Bambu_printerViewModel, construct: Bambu_printerViewModel,
// ViewModels your plugin depends on, e.g. loginStateViewModel, settingsViewModel, ... // ViewModels your plugin depends on, e.g. loginStateViewModel, settingsViewModel, ...
dependencies: ["settingsViewModel", "filesViewModel"], dependencies: ["settingsViewModel", "filesViewModel", "loginStateViewModel", "accessViewModel", "timelapseViewModel"],
// Elements to bind to, e.g. #settings_plugin_bambu_printer, #tab_plugin_bambu_printer, ... // Elements to bind to, e.g. #settings_plugin_bambu_printer, #tab_plugin_bambu_printer, ...
elements: ["#bambu_printer_print_options", "#settings_plugin_bambu_printer"] elements: ["#bambu_printer_print_options", "#settings_plugin_bambu_printer", "#bambu_timelapse"]
}); });
}); });

View File

@ -0,0 +1,71 @@
<div class="row-fluid" id="bambu_timelapse">
<h1>{{ _('Bambu Timelapses') }}</h1>
<div class="pull-right">
<div class="btn-group">
<button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="fas fa-wrench"></i> <span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="javascript:void(0)" data-bind="click: function() { listHelper.changeSorting('name'); }"><i class="fas fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'name' ? 'visible' : 'hidden'}"></i> {{ _('Sort by name') }} ({{ _('ascending') }})</a></li>
<li><a href="javascript:void(0)" data-bind="click: function() { listHelper.changeSorting('date'); }"><i class="fas fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'date' ? 'visible' : 'hidden'}"></i> {{ _('Sort by date') }} ({{ _('descending') }})</a></li>
<li><a href="javascript:void(0)" data-bind="click: function() { listHelper.changeSorting('size'); }"><i class="fas fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'size' ? 'visible' : 'hidden'}"></i> {{ _('Sort by file size') }} ({{ _('descending') }})</a></li>
</ul>
</div>
</div>
<table class="table table-hover table-condensed table-hover" id="bambu_timelapse_files">
<thead>
<tr>
<th class="timelapse_files_thumb"></th>
<th class="timelapse_files_details">{{ _('Details') }}</th>
<th class="timelapse_files_action">{{ _('Action') }}</th>
</tr>
</thead>
<tbody data-bind="foreach: listHelper.paginatedItems">
<tr data-bind="attr: {title: name}">
<td class="timelapse_files_thumb">
<div class="thumb" data-bind="css: { letterbox: $data.thumbnail }">
<!-- ko if: $data.thumbnail -->
<img data-bind="attr:{src: thumbnail}" loading="lazy" style="aspect-ratio: 3 / 2;"/>
<!-- /ko -->
<a href="javascript:void(0)" data-bind="css: {disabled: !$root.timelapseViewModel.isTimelapseViewable($data)}, click: $root.showTimelapseThumbnail"></a>
</div>
</td>
<td class="timelapse_files_details">
<p class="name" data-bind="text: name"></p>
<p class="detail">{{ _('Recorded:') }} <span data-bind="text: formatTimeAgo(timestamp)"/></p>
<p class="detail">{{ _('Size:') }} <span data-bind="text: size"/></p>
</td>
<td class="timelapse_files_action">
<div class="btn-group action-buttons">
<a href="javascript:void(0)" class="btn btn-mini" data-bind="css: {disabled: !$root.loginStateViewModel.hasPermissionKo($root.accessViewModel.permissions.TIMELAPSE_DOWNLOAD)()}, attr: { href: ($root.loginStateViewModel.hasPermission($root.accessViewModel.permissions.TIMELAPSE_DOWNLOAD)) ? $data.url : 'javascript:void(0)' }"><i class="fas fa-download"></i></a>
</div>
</td>
</tr>
</tbody>
</table>
<div class="pagination pagination-mini pagination-centered">
<ul>
<li data-bind="css: {disabled: listHelper.currentPage() === 0}"><a href="javascript:void(0)" data-bind="click: listHelper.prevPage">«</a></li>
</ul>
<ul data-bind="foreach: listHelper.pages">
<li data-bind="css: { active: $data.number === $root.listHelper.currentPage(), disabled: $data.number === -1 }"><a href="javascript:void(0)" data-bind="text: $data.text, click: function() { $root.listHelper.changePage($data.number); }"></a></li>
</ul>
<ul>
<li data-bind="css: {disabled: listHelper.currentPage() === listHelper.lastPage()}"><a href="javascript:void(0)" data-bind="click: listHelper.nextPage">»</a></li>
</ul>
</div>
</div>
<div id="bambu_printer_timelapse_preview" class="modal hide fade">
<div class="modal-header">
<a href="#" class="close" data-dismiss="modal" aria-hidden="true">&times;</a>
<h3>{{ _('Timelapse Thumbnail') }}</h3>
</div>
<div class="modal-body">
<div class="row-fluid">
<img id="bambu_printer_timelapse_thumbnail" src="" class="row-fluid" style="aspect-ratio: 3 / 2;"/>
</div>
</div>
<div class="modal-footer">
<a href="#" class="btn" data-dismiss="modal" aria-hidden="true">{{ _('Close') }}</a>
</div>
</div>

View File

@ -4,6 +4,7 @@ __license__ = "GNU Affero General Public License http://www.gnu.org/licenses/agp
import collections import collections
import datetime import datetime
import math
import os import os
import queue import queue
import re import re
@ -162,13 +163,14 @@ class BambuPrinter:
# self._logger.debug(device_data) # self._logger.debug(device_data)
self.lastTempAt = time.monotonic()
self.temp[0] = temperatures.get("nozzle_temp", 0.0) self.temp[0] = temperatures.get("nozzle_temp", 0.0)
self.targetTemp[0] = temperatures.get("target_nozzle_temp", 0.0) self.targetTemp[0] = temperatures.get("target_nozzle_temp", 0.0)
self.bedTemp = temperatures.get("bed_temp", 0.0) self.bedTemp = temperatures.get("bed_temp", 0.0)
self.bedTargetTemp = temperatures.get("target_bed_temp", 0.0) self.bedTargetTemp = temperatures.get("target_bed_temp", 0.0)
self.chamberTemp = temperatures.get("chamber_temp", 0.0) self.chamberTemp = temperatures.get("chamber_temp", 0.0)
if print_job.get("gcode_state") == "RUNNING" or print_job.get("gcode_state") == "PREPARE": if print_job.get("gcode_state") == "RUNNING":
if not self._sdPrintingSemaphore.is_set(): if not self._sdPrintingSemaphore.is_set():
self._sdPrintingSemaphore.set() self._sdPrintingSemaphore.set()
if self._sdPrintingPausedSemaphore.is_set(): if self._sdPrintingPausedSemaphore.is_set():
@ -181,6 +183,10 @@ class BambuPrinter:
filename = f"{filename.lower()}.3mf" filename = f"{filename.lower()}.3mf"
elif self._sdFileListCache.get(f"{filename.lower()}.gcode.3mf"): elif self._sdFileListCache.get(f"{filename.lower()}.gcode.3mf"):
filename = f"{filename.lower()}.gcode.3mf" filename = f"{filename.lower()}.gcode.3mf"
elif filename.startswith("cache/"):
filename = filename[6:]
else:
self._logger.debug(f"No 3mf file found for {print_job}")
self._selectSdFile(filename) self._selectSdFile(filename)
self._startSdPrint(from_printer=True) self._startSdPrint(from_printer=True)
@ -196,7 +202,7 @@ class BambuPrinter:
self._send("// action:paused") self._send("// action:paused")
self._sendPaused() self._sendPaused()
if ( print_job.get("gcode_state") == "FINISH" or print_job.get("gcode_state") == "FAILED" ): if print_job.get("gcode_state") == "FINISH" or print_job.get("gcode_state") == "FAILED":
if self._sdPrintStarting is False: if self._sdPrintStarting is False:
self._sdPrinting = False self._sdPrinting = False
if self._sdPrintingSemaphore.is_set(): if self._sdPrintingSemaphore.is_set():
@ -211,7 +217,16 @@ class BambuPrinter:
): ):
asyncio.run(self._create_connection_async()) asyncio.run(self._create_connection_async())
def on_disconnect(self, on_disconnect):
self._logger.debug(f"on disconnect called")
return on_disconnect
def on_connect(self, on_connect):
self._logger.debug(f"on connect called")
return on_connect
async def _create_connection_async(self): async def _create_connection_async(self):
self._logger.debug(f"connecting via local mqtt: {self._settings.get_boolean(['local_mqtt'])}")
self.bambu = BambuClient(device_type=self._settings.get(["device_type"]), self.bambu = BambuClient(device_type=self._settings.get(["device_type"]),
serial=self._settings.get(["serial"]), serial=self._settings.get(["serial"]),
host=self._settings.get(["host"]), host=self._settings.get(["host"]),
@ -222,13 +237,11 @@ class BambuPrinter:
email=self._settings.get(["email"]), email=self._settings.get(["email"]),
auth_token=self._settings.get(["auth_token"]) auth_token=self._settings.get(["auth_token"])
) )
self.bambu.on_disconnect = self.on_disconnect(self.bambu.on_disconnect)
self.bambu.on_connect = self.on_connect(self.bambu.on_connect)
self.bambu.connect(callback=self.new_update) self.bambu.connect(callback=self.new_update)
self._logger.info(f"bambu connection status: {self.bambu.connected}") self._logger.info(f"bambu connection status: {self.bambu.connected}")
self._sendOk() self._sendOk()
# while True:
# await asyncio.sleep(self.tick_rate)
# self._processTemperatureQuery()
def __str__(self): def __str__(self):
return "BAMBU(read_timeout={read_timeout},write_timeout={write_timeout},options={options})".format( return "BAMBU(read_timeout={read_timeout},write_timeout={write_timeout},options={options})".format(
@ -554,8 +567,7 @@ class BambuPrinter:
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
def _gcode_M105(self, data: str) -> bool: def _gcode_M105(self, data: str) -> bool:
self._processTemperatureQuery() return self._processTemperatureQuery()
return True
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
def _gcode_M115(self, data: str) -> bool: def _gcode_M115(self, data: str) -> bool:
@ -588,6 +600,26 @@ class BambuPrinter:
self._send(text) self._send(text)
return True return True
# noinspection PyUnusedLocal
def _gcode_M220(self, data: str) -> bool:
if self.bambu.connected:
gcode_command = commands.SEND_GCODE_TEMPLATE
percent = int(data[1:])
if percent is None or percent < 1 or percent > 166:
return True
speed_fraction = 100 / percent
acceleration = math.exp((speed_fraction - 1.0191) / -0.814)
feed_rate = (2.1645 * (acceleration ** 3) - 5.3247 * (acceleration ** 2) + 4.342 * acceleration - 0.181)
speed_level = 1.539 * (acceleration ** 2) - 0.7032 * acceleration + 4.0834
speed_command = f"M204.2 K${acceleration:.2f} \nM220 K${feed_rate:.2f} \nM73.2 R${speed_fraction:.2f} \nM1002 set_gcode_claim_speed_level ${speed_level:.0f}\n"
gcode_command['print']['param'] = speed_command
if self.bambu.publish(gcode_command):
self._logger.info(f"{percent}% speed adjustment command sent successfully")
return True
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
def _gcode_M400(self, data: str) -> bool: def _gcode_M400(self, data: str) -> bool:
return True return True
@ -698,16 +730,20 @@ class BambuPrinter:
return result return result
def _getSdFileData(self, filename: str) -> Optional[Dict[str, Any]]: def _getSdFileData(self, filename: str) -> Optional[Dict[str, Any]]:
self._logger.debug(f"_getSdFileData: {filename}")
data = self._sdFileListCache.get(filename.lower()) data = self._sdFileListCache.get(filename.lower())
if isinstance(data, str): if isinstance(data, str):
data = self._sdFileListCache.get(data.lower()) data = self._sdFileListCache.get(data.lower())
self._logger.debug(f"_getSdFileData: {data}")
return data return data
def _getSdFiles(self) -> List[Dict[str, Any]]: def _getSdFiles(self) -> List[Dict[str, Any]]:
self._sdFileListCache = self._mappedSdList() self._sdFileListCache = self._mappedSdList()
self._logger.debug(f"_getSdFiles return: {self._sdFileListCache}")
return [x for x in self._sdFileListCache.values() if isinstance(x, dict)] return [x for x in self._sdFileListCache.values() if isinstance(x, dict)]
def _selectSdFile(self, filename: str, check_already_open: bool = False) -> None: def _selectSdFile(self, filename: str, check_already_open: bool = False) -> None:
self._logger.debug(f"_selectSdFile: {filename}, check_already_open={check_already_open}")
if filename.startswith("/"): if filename.startswith("/"):
filename = filename[1:] filename = filename[1:]
@ -729,6 +765,7 @@ class BambuPrinter:
self._send("File selected") self._send("File selected")
def _startSdPrint(self, from_printer: bool = False) -> None: def _startSdPrint(self, from_printer: bool = False) -> None:
self._logger.debug(f"_startSdPrint: from_printer={from_printer}")
if self._selectedSdFile is not None: if self._selectedSdFile is not None:
if self._sdPrinter is None: if self._sdPrinter is None:
self._sdPrinting = True self._sdPrinting = True
@ -788,10 +825,14 @@ class BambuPrinter:
output += " @:64\n" output += " @:64\n"
return output return output
def _processTemperatureQuery(self): def _processTemperatureQuery(self) -> bool:
# includeOk = not self._okBeforeCommandOutput # includeOk = not self._okBeforeCommandOutput
if self.bambu.connected:
output = self._generateTemperatureOutput() output = self._generateTemperatureOutput()
self._send(output) self._send(output)
return True
else:
return False
def _writeSdFile(self, filename: str) -> None: def _writeSdFile(self, filename: str) -> None:
self._send(f"Writing to file: {filename}") self._send(f"Writing to file: {filename}")
@ -820,7 +861,13 @@ class BambuPrinter:
print_command = {"print": {"sequence_id": 0, print_command = {"print": {"sequence_id": 0,
"command": "project_file", "command": "project_file",
"param": "Metadata/plate_1.gcode", "param": "Metadata/plate_1.gcode",
"md5": "",
"profile_id": "0",
"project_id": "0",
"subtask_id": "0",
"task_id": "0",
"subtask_name": f"{self._selectedSdFile}", "subtask_name": f"{self._selectedSdFile}",
"file": f"{self._selectedSdFile}",
"url": f"file:///mnt/sdcard/{self._selectedSdFile}" if self._settings.get_boolean(["device_type"]) in ["X1", "X1C"] else f"file:///sdcard/{self._selectedSdFile}", "url": f"file:///mnt/sdcard/{self._selectedSdFile}" if self._settings.get_boolean(["device_type"]) in ["X1", "X1C"] else f"file:///sdcard/{self._selectedSdFile}",
"timelapse": self._settings.get_boolean(["timelapse"]), "timelapse": self._settings.get_boolean(["timelapse"]),
"bed_leveling": self._settings.get_boolean(["bed_leveling"]), "bed_leveling": self._settings.get_boolean(["bed_leveling"]),

View File

@ -14,7 +14,7 @@ plugin_package = "octoprint_bambu_printer"
plugin_name = "OctoPrint-BambuPrinter" plugin_name = "OctoPrint-BambuPrinter"
# The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module # The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module
plugin_version = "0.0.17" plugin_version = "0.0.22"
# The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin # The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin
# module # module