Implement Configpath and Logpath Validation

Added JS popup handler. Added configpath and logpath validation when settings are saved.
Add logpath validation


Change file checking method


Check new values instead of old settings on save
This commit is contained in:
Alice Grey 2020-09-07 11:37:01 -05:00
parent a2291b1a3d
commit e553a69ff5
2 changed files with 179 additions and 134 deletions

View File

@ -81,41 +81,55 @@ class KlipperPlugin(
def on_settings_load(self): def on_settings_load(self):
data = octoprint.plugin.SettingsPlugin.on_settings_load(self) data = octoprint.plugin.SettingsPlugin.on_settings_load(self)
filepath = os.path.expanduser( configpath = os.path.expanduser(
self._settings.get(["configuration", "configpath"]) self._settings.get(["configuration", "configpath"])
) )
logpath = os.path.expanduser(
self._settings.get(["configuration", "logpath"])
)
try: try:
f = open(filepath, "r") f = open(configpath, "r")
data["config"] = f.read() data["config"] = f.read()
f.close() f.close()
except IOError: except IOError:
self._logger.error( self._logger.error(
"Error: Klipper config file not found at: {}".format(filepath) "Error: Klipper config file not found at: {}".format(configpath)
) )
return data return data
def on_settings_save(self, data): def on_settings_save(self, data):
if self.keyexists(data, "configuration", "configpath"):
configpath = os.path.expanduser(
data["configuration"]["configpath"]
)
self.checkFile("config",configpath)
if self.keyexists(data, "configuration", "logpath"):
logpath = os.path.expanduser(
data["configuration"]["logpath"]
)
self.checkFile("log",logpath)
if "config" in data: if "config" in data:
try: try:
filepath = os.path.expanduser(
self._settings.get(["configuration", "configpath"])
)
data["config"] = data["config"].encode('utf-8') data["config"] = data["config"].encode('utf-8')
f = open(filepath, "w") f = open(configpath, "w")
f.write(data["config"]) f.write(data["config"])
f.close() f.close()
self._logger.info( self._logger.error(
"Writing Klipper config to {}".format(filepath) "Writing Klipper config to {}".format(configpath)
) )
# Restart klipply to reload config # Restart klipply to reload config
self._printer.commands(self._settings.get(["configuration", "reload_command"])) self._printer.commands(self._settings.get(["configuration", "reload_command"]))
self.logInfo("Reloading Klipper Configuration.") self.logInfo("Reloading Klipper Configuration.")
except IOError: except IOError:
self._logger.error( self._logger.error(
"Error: Couldn't write Klipper config file: {}".format(filepath) "Error: Couldn't write Klipper config file: {}".format(configpath)
) )
data.pop("config", None) # we dont want to write the klipper conf to the octoprint settings data.pop("config", None) # we dont want to write the klipper conf to the octoprint settings
else: else:
octoprint.plugin.SettingsPlugin.on_settings_save(self, data) octoprint.plugin.SettingsPlugin.on_settings_save(self, data)
@ -324,13 +338,14 @@ class KlipperPlugin(
) )
#-- Helpers #-- Helpers
def sendMessage(self, type, subtype, payload): def sendMessage(self, type, subtype, title, payload):
self._plugin_manager.send_plugin_message( self._plugin_manager.send_plugin_message(
self._identifier, self._identifier,
dict( dict(
time=datetime.datetime.now().strftime("%H:%M:%S"), time=datetime.datetime.now().strftime("%H:%M:%S"),
type=type, type=type,
subtype=subtype, subtype=subtype,
title=title,
payload=payload payload=payload
) )
) )
@ -339,13 +354,25 @@ class KlipperPlugin(
self._printer.commands("STATUS") self._printer.commands("STATUS")
def updateStatus(self, type, status): def updateStatus(self, type, status):
self.sendMessage("status", type, status) self.sendMessage("status", type, status, status)
def logInfo(self, message): def logInfo(self, message):
self.sendMessage("log", "info", message) self.sendMessage("log", "info", message, message)
def logError(self, error): def logError(self, error):
self.sendMessage("log", "error", error) self.sendMessage("log", "error", error, error)
def checkFile(self,filetype,filepath):
if not os.path.isfile(filepath):
self.sendMessage("errorPopUp","warning", "OctoKlipper Settings", "Klipper " + filepath + " does not exist!")
def keyexists(self, dict, key1, key2):
try:
dict[key1][key2]
except KeyError:
return False
else:
return True
__plugin_name__ = "OctoKlipper" __plugin_name__ = "OctoKlipper"
__plugin_pythoncompat__ = ">=2.7,<4" __plugin_pythoncompat__ = ">=2.7,<4"

View File

@ -14,126 +14,144 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
$(function() { $(function() {
function KlipperViewModel(parameters) { function KlipperViewModel(parameters) {
var self = this; var self = this;
self.settings = parameters[0]; self.settings = parameters[0];
self.loginState = parameters[1]; self.loginState = parameters[1];
self.connectionState = parameters[2]; self.connectionState = parameters[2];
self.levelingViewModel = parameters[3]; self.levelingViewModel = parameters[3];
self.paramMacroViewModel = parameters[4]; self.paramMacroViewModel = parameters[4];
self.shortStatus = ko.observable(); self.shortStatus = ko.observable();
self.logMessages = ko.observableArray(); self.logMessages = ko.observableArray();
self.showLevelingDialog = function() {
var dialog = $("#klipper_leveling_dialog");
dialog.modal({
show: 'true',
backdrop: 'static',
keyboard: false
});
self.levelingViewModel.initView();
}
self.showPidTuningDialog = function() {
var dialog = $("#klipper_pid_tuning_dialog");
dialog.modal({
show: 'true',
backdrop: 'static',
keyboard: false
});
}
self.showOffsetDialog = function() {
var dialog = $("#klipper_offset_dialog");
dialog.modal({
show: 'true',
backdrop: 'static'
});
}
self.showGraphDialog = function() {
var dialog = $("#klipper_graph_dialog");
dialog.modal({
show: 'true',
minHeight: "500px",
maxHeight: "600px"
});
}
self.executeMacro = function(macro) {
var paramObjRegex = /{(.*?)}/g;
if (macro.macro().match(paramObjRegex) == null) {
OctoPrint.control.sendGcode(
// Use .split to create an array of strings which is sent to
// OctoPrint.control.sendGcode instead of a single string.
macro.macro().split(/\r\n|\r|\n/)
);
} else {
self.paramMacroViewModel.process(macro);
var dialog = $("#klipper_macro_dialog");
dialog.modal({
show: 'true',
backdrop: 'static'
});
}
}
self.onGetStatus = function() {
OctoPrint.control.sendGcode("Status")
}
self.onRestartFirmware = function() {
OctoPrint.control.sendGcode("FIRMWARE_RESTART")
};
self.onRestartHost = function() {
OctoPrint.control.sendGcode("RESTART")
};
self.onAfterBinding = function() {
self.connectionState.selectedPort(self.settings.settings.plugins.klipper.connection.port());
}
self.onDataUpdaterPluginMessage = function(plugin, message) {
if(plugin == "klipper") {
if(message["type"] == "status") {
self.shortStatus(message["payload"]);
} else {
self.logMessage(message["time"], message["subtype"], message["payload"]);
}
}
}
self.logMessage = function(timestamp, type, message) { self.showPopUp = function(popupType, popupTitle, message){
self.logMessages.push({ var title = popupType.toUpperCase() + ": " + popupTitle;
time: timestamp, new PNotify({
type: type, title: title,
msg: message.replace(/\n/gi, "<br>")} text: message,
); type: popupType,
} hide: false
});
self.onClearLog = function() { };
self.logMessages.removeAll();
}; self.showLevelingDialog = function() {
var dialog = $("#klipper_leveling_dialog");
self.isActive = function() { dialog.modal({
return self.connectionState.isOperational() && self.loginState.isUser(); show: 'true',
} backdrop: 'static',
} keyboard: false
});
self.levelingViewModel.initView();
};
self.showPidTuningDialog = function() {
var dialog = $("#klipper_pid_tuning_dialog");
dialog.modal({
show: 'true',
backdrop: 'static',
keyboard: false
});
};
self.showOffsetDialog = function() {
var dialog = $("#klipper_offset_dialog");
dialog.modal({
show: 'true',
backdrop: 'static'
});
};
self.showGraphDialog = function() {
var dialog = $("#klipper_graph_dialog");
dialog.modal({
show: 'true',
minHeight: "500px",
maxHeight: "600px"
});
};
self.executeMacro = function(macro) {
var paramObjRegex = /{(.*?)}/g;
if (macro.macro().match(paramObjRegex) == null) {
OctoPrint.control.sendGcode(
// Use .split to create an array of strings which is sent to
// OctoPrint.control.sendGcode instead of a single string.
macro.macro().split(/\r\n|\r|\n/)
);
} else {
self.paramMacroViewModel.process(macro);
var dialog = $("#klipper_macro_dialog");
dialog.modal({
show: 'true',
backdrop: 'static'
});
}
};
self.onGetStatus = function() {
OctoPrint.control.sendGcode("Status")
};
self.onRestartFirmware = function() {
OctoPrint.control.sendGcode("FIRMWARE_RESTART")
};
self.onRestartHost = function() {
OctoPrint.control.sendGcode("RESTART")
};
self.onAfterBinding = function() {
self.connectionState.selectedPort(self.settings.settings.plugins.klipper.connection.port());
};
self.onDataUpdaterPluginMessage = function(plugin, data) {
if(plugin == "klipper") {
if ("warningPopUp" == data.type){
self.showPopUp(data.subtype, data.title, data.payload);
return;
}
if ("errorPopUp" == data.type){
self.showPopUp(data.subtype, data.title, data.payload);
return;
}
if(data.type == "status") {
self.shortStatus(data.payload);
} else {
self.logMessage(data.time, data.subtype, data.payload);
}
}
};
OCTOPRINT_VIEWMODELS.push({ self.logMessage = function(timestamp, type, message) {
construct: KlipperViewModel, self.logMessages.push({
dependencies: [ time: timestamp,
"settingsViewModel", type: type,
"loginStateViewModel", msg: message.replace(/\n/gi, "<br>")}
"connectionViewModel", );
"klipperLevelingViewModel", };
"klipperMacroDialogViewModel"
], self.onClearLog = function() {
elements: ["#tab_plugin_klipper_main", "#sidebar_plugin_klipper", "#navbar_plugin_klipper"] self.logMessages.removeAll();
}); };
self.isActive = function() {
return self.connectionState.isOperational() && self.loginState.isUser();
};
}
OCTOPRINT_VIEWMODELS.push({
construct: KlipperViewModel,
dependencies: [
"settingsViewModel",
"loginStateViewModel",
"connectionViewModel",
"klipperLevelingViewModel",
"klipperMacroDialogViewModel"
],
elements: ["#tab_plugin_klipper_main", "#sidebar_plugin_klipper", "#navbar_plugin_klipper"]
});
}); });