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):
data = octoprint.plugin.SettingsPlugin.on_settings_load(self)
filepath = os.path.expanduser(
configpath = os.path.expanduser(
self._settings.get(["configuration", "configpath"])
)
logpath = os.path.expanduser(
self._settings.get(["configuration", "logpath"])
)
try:
f = open(filepath, "r")
f = open(configpath, "r")
data["config"] = f.read()
f.close()
except IOError:
self._logger.error(
"Error: Klipper config file not found at: {}".format(filepath)
"Error: Klipper config file not found at: {}".format(configpath)
)
return 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:
try:
filepath = os.path.expanduser(
self._settings.get(["configuration", "configpath"])
)
data["config"] = data["config"].encode('utf-8')
f = open(filepath, "w")
f = open(configpath, "w")
f.write(data["config"])
f.close()
self._logger.info(
"Writing Klipper config to {}".format(filepath)
self._logger.error(
"Writing Klipper config to {}".format(configpath)
)
# Restart klipply to reload config
self._printer.commands(self._settings.get(["configuration", "reload_command"]))
self.logInfo("Reloading Klipper Configuration.")
except IOError:
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:
octoprint.plugin.SettingsPlugin.on_settings_save(self, data)
@ -324,13 +338,14 @@ class KlipperPlugin(
)
#-- Helpers
def sendMessage(self, type, subtype, payload):
def sendMessage(self, type, subtype, title, payload):
self._plugin_manager.send_plugin_message(
self._identifier,
dict(
time=datetime.datetime.now().strftime("%H:%M:%S"),
type=type,
subtype=subtype,
title=title,
payload=payload
)
)
@ -339,13 +354,25 @@ class KlipperPlugin(
self._printer.commands("STATUS")
def updateStatus(self, type, status):
self.sendMessage("status", type, status)
self.sendMessage("status", type, status, status)
def logInfo(self, message):
self.sendMessage("log", "info", message)
self.sendMessage("log", "info", message, message)
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_pythoncompat__ = ">=2.7,<4"

View File

@ -14,126 +14,144 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
$(function() {
function KlipperViewModel(parameters) {
var self = this;
function KlipperViewModel(parameters) {
var self = this;
self.settings = parameters[0];
self.loginState = parameters[1];
self.connectionState = parameters[2];
self.levelingViewModel = parameters[3];
self.paramMacroViewModel = parameters[4];
self.shortStatus = ko.observable();
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.settings = parameters[0];
self.loginState = parameters[1];
self.connectionState = parameters[2];
self.levelingViewModel = parameters[3];
self.paramMacroViewModel = parameters[4];
self.shortStatus = ko.observable();
self.logMessages = ko.observableArray();
self.logMessage = function(timestamp, type, message) {
self.logMessages.push({
time: timestamp,
type: type,
msg: message.replace(/\n/gi, "<br>")}
);
}
self.onClearLog = function() {
self.logMessages.removeAll();
};
self.isActive = function() {
return self.connectionState.isOperational() && self.loginState.isUser();
}
}
self.showPopUp = function(popupType, popupTitle, message){
var title = popupType.toUpperCase() + ": " + popupTitle;
new PNotify({
title: title,
text: message,
type: popupType,
hide: false
});
};
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, 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({
construct: KlipperViewModel,
dependencies: [
"settingsViewModel",
"loginStateViewModel",
"connectionViewModel",
"klipperLevelingViewModel",
"klipperMacroDialogViewModel"
],
elements: ["#tab_plugin_klipper_main", "#sidebar_plugin_klipper", "#navbar_plugin_klipper"]
});
self.logMessage = function(timestamp, type, message) {
self.logMessages.push({
time: timestamp,
type: type,
msg: message.replace(/\n/gi, "<br>")}
);
};
self.onClearLog = function() {
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"]
});
});