-Bump for 0.3.4rc2

-fix for errorexception
-added extern logfile
This commit is contained in:
thelastWallE 2021-03-29 00:57:23 +02:00
parent 95da175825
commit 2aec1a9eaa
6 changed files with 186 additions and 78 deletions

View File

@ -41,9 +41,25 @@ class KlipperPlugin(
octoprint.plugin.EventHandlerPlugin): octoprint.plugin.EventHandlerPlugin):
_parsing_response = False _parsing_response = False
_parsing_check_response = False
_message = "" _message = ""
def __init__(self):
self._logger = logging.getLogger("octoprint.plugins.klipper")
self._octoklipper_logger = logging.getLogger("octoprint.plugins.klipper.debug")
# -- Startup Plugin # -- Startup Plugin
def on_startup(self, host, port):
from octoprint.logging.handlers import CleaningTimedRotatingFileHandler
octoklipper_logging_handler = CleaningTimedRotatingFileHandler(
self._settings.get_plugin_logfile_path(postfix="debug"), when="D", backupCount=3)
octoklipper_logging_handler.setFormatter(logging.Formatter("[%(asctime)s] %(levelname)s: %(message)s"))
octoklipper_logging_handler.setLevel(logging.DEBUG)
self._octoklipper_logger.addHandler(octoklipper_logging_handler)
self._octoklipper_logger.setLevel(
logging.DEBUG if self._settings.get_boolean(["debug_logging"]) else logging.INFO)
self._octoklipper_logger.propagate = False
def on_after_startup(self): def on_after_startup(self):
klipper_port = self._settings.get(["connection", "port"]) klipper_port = self._settings.get(["connection", "port"])
@ -55,7 +71,7 @@ class KlipperPlugin(
self._settings.global_set( self._settings.global_set(
["serial", "additionalPorts"], additional_ports) ["serial", "additionalPorts"], additional_ports)
self._settings.save() self._settings.save()
self._logger.info( self.log_info(
"Added klipper serial port {} to list of additional ports.".format(klipper_port)) "Added klipper serial port {} to list of additional ports.".format(klipper_port))
# -- Settings Plugin # -- Settings Plugin
@ -104,7 +120,9 @@ class KlipperPlugin(
)] )]
), ),
configuration=dict( configuration=dict(
debug_logging=False,
configpath="~/printer.cfg", configpath="~/printer.cfg",
old_config="",
logpath="/tmp/klippy.log", logpath="/tmp/klippy.log",
reload_command="RESTART", reload_command="RESTART",
navbar=True navbar=True
@ -123,7 +141,7 @@ class KlipperPlugin(
data["config"] = f.read() data["config"] = f.read()
f.close() f.close()
except IOError: except IOError:
self._logger.error( self.log_error(
"Error: Klipper config file not found at: {}".format( "Error: Klipper config file not found at: {}".format(
configpath) configpath)
) )
@ -134,8 +152,7 @@ class KlipperPlugin(
def on_settings_save(self, data): def on_settings_save(self, data):
self.log_console( self.log_debug(
"debug",
"Save klipper configs" "Save klipper configs"
) )
@ -154,8 +171,7 @@ class KlipperPlugin(
configpath = os.path.expanduser( configpath = os.path.expanduser(
self._settings.get(["configuration", "configpath"]) self._settings.get(["configuration", "configpath"])
) )
if self.file_exist(configpath) and self._parsing_check_response:
if self.file_exist(configpath) and self.validate_configfile(data["config"]):
f = open(configpath, "w") f = open(configpath, "w")
f.write(data["config"]) f.write(data["config"])
f.close() f.close()
@ -163,23 +179,25 @@ class KlipperPlugin(
self._printer.commands(self._settings.get( self._printer.commands(self._settings.get(
["configuration", "reload_command"])) ["configuration", "reload_command"]))
self.log_info("Reloading Klipper Configuration.") self.log_info("Reloading Klipper Configuration.")
self.log_console( self.log_debug("Writing Klipper config to {}".format(configpath))
"debug",
("Writing Klipper config to {}".format(configpath))
)
except IOError: except IOError:
self._logger.error( self.log_error("Error: Couldn't write Klipper config file: {}".format(configpath))
"Error: Couldn't write Klipper config file: {}".format(
configpath)
)
else: else:
# we dont want to write the klipper conf to the octoprint settings # we dont want to write the klipper conf to the octoprint settings
data.pop("config", None) data.pop("config", None)
# save the rest of changed settings into config.yaml of octoprint # save the rest of changed settings into config.yaml of octoprint
old_debug_logging = self._settings.get_boolean(["configuration", "debug_logging"])
octoprint.plugin.SettingsPlugin.on_settings_save(self, data) octoprint.plugin.SettingsPlugin.on_settings_save(self, data)
new_debug_logging = self._settings.get_boolean(["configuration", "debug_logging"])
if old_debug_logging != new_debug_logging:
if new_debug_logging:
self._octoklipper_logger.setLevel(logging.DEBUG)
else:
self._octoklipper_logger.setLevel(logging.INFO)
def get_settings_restricted_paths(self): def get_settings_restricted_paths(self):
return dict( return dict(
admin=[ admin=[
@ -357,7 +375,8 @@ class KlipperPlugin(
return dict( return dict(
listLogFiles=[], listLogFiles=[],
getStats=["logFile"], getStats=["logFile"],
reloadConfig=[] reloadConfig=[],
checkConfig=["config"]
) )
def on_api_command(self, command, data): def on_api_command(self, command, data):
@ -395,15 +414,25 @@ class KlipperPlugin(
data["config"] = f.read() data["config"] = f.read()
f.close() f.close()
except IOError: except IOError:
self._logger.error( self.log_error(
"Error: Klipper config file not found at: {}".format( "Error: Klipper config file not found at: {}".format(
configpath) configpath)
) )
else: else:
self._settings.set(["config"], data["config"]) self._settings.set(["config"], data["config"])
self.send_message("reload", "config", "", data["config"]) # self.send_message("reload", "config", "", data["config"])
# send the configdata to frontend to update ace editor # send the configdata to frontend to update ace editor
return return flask.jsonify(data=data["config"])
elif command == "checkConfig":
if "config" in data:
self.log_debug("config in ")
if not self.validate_configfile(data["config"]):
self.log_debug("validateConfig ->" + data["config"])
self._settings.set(["configuration", "old_config"], data["config"])
return flask.jsonify(checkConfig="not OK")
else:
self._settings.set(["configuration", "old_config"], "")
return flask.jsonify(checkConfig="OK")
def get_update_information(self): def get_update_information(self):
return dict( return dict(
@ -449,19 +478,24 @@ class KlipperPlugin(
self.send_message("status", type, status, status) self.send_message("status", type, status, status)
def log_info(self, message): def log_info(self, message):
self._octoklipper_logger.info(message)
self.send_message("log", "info", message, message) self.send_message("log", "info", message, message)
self.send_message("console", "info", message, message)
def log_console(self, consoletype, message): def log_debug(self, message):
self._octoklipper_logger.debug(message)
# sends a message to frontend(in klipper.js -> self.onDataUpdaterPluginMessage) and write it to the console. # sends a message to frontend(in klipper.js -> self.onDataUpdaterPluginMessage) and write it to the console.
# _mtype, subtype=debug/info, title of message, message) # _mtype, subtype=debug/info, title of message, message)
self.send_message("console", consoletype, message, message) self.send_message("console", "debug", message, message)
def log_error(self, error): def log_error(self, error):
self._octoklipper_logger.error(error)
self.send_message("log", "error", error, error) self.send_message("log", "error", error, error)
self.send_message("console", "error", error, error)
def file_exist(self, filepath): def file_exist(self, filepath):
if not os.path.isfile(filepath): if not os.path.isfile(filepath):
self.send_message("errorPopUp", "warning", "OctoKlipper Settings", self.send_message("PopUp", "warning", "OctoKlipper Settings",
"Klipper " + filepath + " does not exist!") "Klipper " + filepath + " does not exist!")
return False return False
else: else:
@ -498,15 +532,22 @@ class KlipperPlugin(
try: try:
dataToValidated = configparser.RawConfigParser() dataToValidated = configparser.RawConfigParser()
dataToValidated.read_string(dataToBeValidated) dataToValidated.read_string(dataToBeValidated)
except dataToValidated.Error as error: except configparser.Error as error:
self._logger.error( error.message = error.message.replace("\n","")
"Error: Invalid Klipper config file: {}".format(str(error)) error.source = "Klipper config"
self.log_error(
"Error: Invalid Klipper config file:\n" +
"{}".format(str(error))
) )
self.send_message("errorPopUp", "warning", "OctoKlipper Settings", self.send_message("PopUp", "warning", "Invalid Config",
"Invalid Klipper config file: " + str(error)) "Config got not saved!\n" +
return "False" "You can reload your last changes\n" +
"on the file editor tab.\n\n" + str(error))
self._parsing_check_response = False
return
else: else:
return "True" self._parsing_check_response = True
return
#incorrectlines = [] #incorrectlines = []
# for section in dataToValidated.sections(): # for section in dataToValidated.sections():

View File

@ -102,6 +102,12 @@ ul#klipper-settings {
height: 99%; height: 99%;
} }
div#settings_plugin_klipper form div.tab-content #confdiv.tap-pane div.control-group button {
width: 30%;
display: inline-block;
margin: 2px;
}
#macros #item.control-group { #macros #item.control-group {
margin-bottom: 2px; margin-bottom: 2px;
border: 2px solid #ccc; border: 2px solid #ccc;

View File

@ -131,30 +131,37 @@ $(function () {
self.onDataUpdaterPluginMessage = function(plugin, data) { self.onDataUpdaterPluginMessage = function(plugin, data) {
if(plugin == "klipper") { if(plugin == "klipper") {
if ("warningPopUp" == data.type){ switch(data.type) {
self.showPopUp(data.subtype, data.title, data.payload); case "PopUp":
return; self.showPopUp(data.subtype, data.title, data.payload);
break;
case "reload":
break;
case "console":
self.consoleMessage(data.subtype, data.payload);
break;
case "status":
self.shortStatus(data.payload);
break;
default:
self.logMessage(data.time, data.subtype, data.payload);
} }
if ("errorPopUp" == data.type){ //if ("warningPopUp" == data.type){
self.showPopUp(data.subtype, data.title, data.payload); // self.showPopUp(data.subtype, data.title, data.payload);
return; // return;
} //} else if ("errorPopUp" == data.type){
// self.showPopUp(data.subtype, data.title, data.payload);
if ("console" == data.type) { // return;
self.consoleMessage(data.subtype, data.payload); //} else if ("reload" == data.type){
return; // return;
} //} else if ("console" == data.type) {
// self.consoleMessage(data.subtype, data.payload);
if ("reload" == data.type){ //} else if (data.type == "status") {
return; // self.shortStatus(data.payload);
} //} else {
// self.logMessage(data.time, data.subtype, data.payload);
if(data.type == "status") { //}
self.shortStatus(data.payload);
} else {
self.logMessage(data.time, data.subtype, data.payload);
}
} }
}; };
@ -166,6 +173,19 @@ $(function () {
}); });
}; };
self.consoleMessage = function (type, message) {
if (type == "info"){
console.info("OctoKlipper : " + message);
} else if (type == "debug"){
if (console_debug){
console.debug("OctoKlipper : " + message);
}
} else {
console.error("OctoKlipper : " + message);
}
return
};
self.reloadConfig = function() { self.reloadConfig = function() {
var settings = { var settings = {
"crossDomain": true, "crossDomain": true,
@ -184,19 +204,6 @@ $(function () {
}); });
} }
self.consoleMessage = function (type, message) {
if (type == "info"){
console.info("OctoKlipper : " + message);
} else {
if (console_debug){
console.debug("OctoKlipper : " + message);
} else {
return
}
}
return
}
self.onClearLog = function () { self.onClearLog = function () {
self.logMessages.removeAll(); self.logMessages.removeAll();
}; };
@ -230,17 +237,17 @@ $(function () {
OCTOPRINT_VIEWMODELS.push({ OCTOPRINT_VIEWMODELS.push({
construct: KlipperViewModel, construct: KlipperViewModel,
dependencies: [ dependencies: [
"settingsViewModel", "settingsViewModel",
"loginStateViewModel", "loginStateViewModel",
"connectionViewModel", "connectionViewModel",
"klipperLevelingViewModel", "klipperLevelingViewModel",
"klipperMacroDialogViewModel", "klipperMacroDialogViewModel",
"accessViewModel" "accessViewModel"
], ],
elements: [ elements: [
"#tab_plugin_klipper_main", "#tab_plugin_klipper_main",
"#sidebar_plugin_klipper", "#sidebar_plugin_klipper",
"#navbar_plugin_klipper" "#navbar_plugin_klipper"
] ]
}); });
}); });

View File

@ -29,6 +29,25 @@ $(function() {
self.apiUrl = OctoPrint.getSimpleApiUrl("klipper"); self.apiUrl = OctoPrint.getSimpleApiUrl("klipper");
self.onSettingsBeforeSave = function () {
if (editor.session) {
//console.debug("OctoKlipper : onSettingsBeforeSave:" + editor.session.getValue())
var settings = {
"crossDomain": true,
"url": self.apiUrl,
"method": "POST",
"headers": self.header,
"processData": false,
"dataType": "json",
"data": JSON.stringify({command: "checkConfig",
config: editor.session.getValue()})
}
$.ajax(settings).done(function (response) {
});
}
}
self.addMacro = function() { self.addMacro = function() {
self.settings.settings.plugins.klipper.macros.push({ self.settings.settings.plugins.klipper.macros.push({
name: 'Macro', name: 'Macro',
@ -87,6 +106,35 @@ $(function() {
} }
} }
self.loadLastSession = function () {
if (self.settings.settings.plugins.klipper.configuration.old_config() != "") {
console.debug("OctoKlipper : lastSession:" + self.settings.settings.plugins.klipper.configuration.old_config())
if (editor.session) {
editor.session.setValue(self.settings.settings.plugins.klipper.configuration.old_config());
editor.clearSelection();
}
}
}
self.reloadFromFile = function () {
if (editor.session) {
var settings = {
"crossDomain": true,
"url": self.apiUrl,
"method": "POST",
"headers": self.header,
"processData": false,
"dataType": "json",
"data": JSON.stringify({command: "reloadConfig"})
}
$.ajax(settings).done(function (response) {
editor.session.setValue(response["data"]);
editor.clearSelection();
});
}
}
self.configBound = function (config) { self.configBound = function (config) {
config.withSilence = function() { config.withSilence = function() {
this.notifySubscribers = function() { this.notifySubscribers = function() {

View File

@ -197,8 +197,14 @@
<script src="plugin/klipper/static/js/lib/ace/ace.min.js" type="text/javascript" charset="utf-8"></script> <script src="plugin/klipper/static/js/lib/ace/ace.min.js" type="text/javascript" charset="utf-8"></script>
<script src="plugin/klipper/static/js/lib/ace/theme-monokai.min.js" type="text/javascript" charset="utf-8"></script> <script src="plugin/klipper/static/js/lib/ace/theme-monokai.min.js" type="text/javascript" charset="utf-8"></script>
<script src="plugin/klipper/static/js/lib/ace/mode-klipper_config.js" type="text/javascript"></script> <script src="plugin/klipper/static/js/lib/ace/mode-klipper_config.js" type="text/javascript"></script>
<button class="btn btn-small" data-bind='click: loadLastSession'
title="Reloads the last changes">
<i class="fas fa-redo"></i> {{ _('Reload last changes') }}
</button><button class="btn btn-small" data-bind='click: reloadFromFile'>
<i class="fas fa-upload"></i></a> {{ _('Reload from file') }}
</button>
<!-- <!--
<a href='#' data-bind='click: onReloadConfig'><i class="icon-refresh"></i></a> {{ _('Reload Configfile') }} <a href='#' data-bind='click: loadLastSession'><i class="fas fa-redo"></i></a> {{ _('Reload last changes') }}<a href='#' data-bind='click: loadLastSession'><i class="fas fa-upload"></i></a> {{ _('Reload from file') }}
--> -->
<input id="hdnLoadKlipperConfig" type="hidden" data-bind="value: configBound(settings.settings.plugins.klipper.config)" /> <input id="hdnLoadKlipperConfig" type="hidden" data-bind="value: configBound(settings.settings.plugins.klipper.config)" />
<div id="plugin-klipper-config"></div> <div id="plugin-klipper-config"></div>

View File

@ -19,7 +19,7 @@ plugin_package = "octoprint_klipper"
plugin_name = "OctoKlipper" plugin_name = "OctoKlipper"
plugin_version = "0.3.4rc1" plugin_version = "0.3.4rc2"
plugin_description = """A plugin for OctoPrint to configure,control and monitor the Klipper 3D printer software.""" plugin_description = """A plugin for OctoPrint to configure,control and monitor the Klipper 3D printer software."""