Skip to content

Commit e023386

Browse files
committed
Add Upload&Print Gcode option
- Allow to specify URL/API key - Upload&Print directly - Document what needs to be configured
1 parent 5ad61d5 commit e023386

File tree

3 files changed

+99
-13
lines changed

3 files changed

+99
-13
lines changed

js/createform.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,9 +459,31 @@ var preview = /*html*/ `<p>It is advised to preview the generated gcode through
459459

460460
var downloadGcodeHtml = /*html*/ `<h4>Download</h4>
461461
<p><label>Filename: <input type="text" name="{formName}_filename" value="{formName}"></label></p>
462-
<p><input type="button" onclick="downloadGcode(form, form['{formName}_filename'].value)" value="Download Gcode"></p>
462+
<p><input type="button" onclick="downloadGcode(form, form['{formName}_filename'].value)" value="Download Gcode">
463+
<input type="button" onclick="uploadGcode(form, form['{formName}_filename'].value)" value="Upload&Print Gcode"></p>
463464
<p><input type="button" onclick="resetFormToDefaults(form)" value="Reset parameters">
464465
<input type="button" onclick="downloadSettings(form, form['{formName}_filename'].value)" value="Output Settings Summary"></p>
466+
467+
<h4>Octoprint / Moonraker</h4>
468+
<p>You can directly print from this website if you specify <b>Octoprint</b> or <b>Moonraker</b> server.</p>
469+
<p><label>URL: <input type="text" name="octoprint_url"></label>
470+
<label>API Key: <input type="password" name="octoprint_key"></label></p>
471+
<div class="octoprintExp">
472+
<label>Configure Octoprint:</label>
473+
<ul>
474+
<li>Get API Key go to <b>User Settings > Application Keys</b> and manually generate new application key.</li>
475+
<li>Enable CORS support by going to <b>OctoPrint Settings > API</b> and checking <b>Allow Cross Origin Resource Sharing (CORS)</b>. Restart afterwards</li>
476+
<li>Restart afterwards</li>
477+
</ul>
478+
479+
<label>Configure Moonraker if used with Klipper:</label>
480+
<ul>
481+
<li>As part of the <a href="https://moonraker.readthedocs.io/en/latest/configuration/#authorization">[authorization] config</a>
482+
add to <b>cors_domains:</b> the <b><script>document.write(window.location.origin);</script></b>.</li>
483+
<li>Restart afterwards</li>
484+
</ul>
485+
</div>
486+
465487
`;
466488

467489
function createForm(n){

js/gcodeprocessing.js

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -700,30 +700,93 @@ function outputSettings(formName) {
700700
return string;
701701
}
702702

703-
704-
function downloadGcode(form, fileName) {
703+
function getGcodeAndSettings(form) {
705704
var gcode = processGcode(form);
706705
var settings = outputSettings(form);
707706

708-
// process finished gcode file
707+
var output = "";
708+
// prefix each line with ; to indicate comment
709+
output += "; " + settings.replaceAll("\n", "\n; ");
710+
output += gcode;
711+
return output;
712+
}
713+
714+
function downloadGcode(form, fileName) {
709715
if (!fileName) {
710716
fileName = form.description.value;
711717
}
712718
fileName += ".gcode";
713719

714-
var output = "";
715-
// prefix each line with ; to indicate comment
716-
output += "; " + settings.replaceAll("\n", "\n; ");
717-
output += gcode;
718-
downloadFile(fileName, output);
720+
downloadFile(fileName, getGcodeAndSettings(form));
719721
}
720722

721723
function downloadSettings(form, fileName) {
722-
var settings = outputSettings(form);
723-
724724
if (!fileName) {
725725
fileName = form.description.value;
726726
}
727-
fileName += "settings.txt";
728-
downloadFile(fileName, settings);
727+
fileName += ".gcode";
728+
729+
downloadFile(fileName, outputSettings(form));
730+
}
731+
732+
function uploadGcode(form, fileName) {
733+
var output = getGcodeAndSettings(form);
734+
735+
if (!form.octoprint_url.value) {
736+
alert("No URL specified for Octoprint or Moonraker.");
737+
return;
738+
}
739+
740+
// get only basename
741+
if (!fileName) {
742+
fileName = form.description.value + ".gcode";
743+
}
744+
fileName = fileName.split('/').reverse()[0];
745+
746+
// remove `/` from the end of URL
747+
var url = form.octoprint_url.value.replace(/\/$/, '');
748+
url += "/api/files/local";
749+
750+
// this detects a `mixed-context` scenario:
751+
// sending request to `http:` when connected via `https:` is not possible
752+
if (window.location.protocol == "https:" && url.toLowerCase().startsWith("http:")) {
753+
httpUrl = window.location.href.replace('https:', 'http:');
754+
755+
alert("Your local Octoprint/Moonraker uses `http://`. " +
756+
"You need to open the `" + httpUrl + "` instead");
757+
return;
758+
}
759+
760+
const formData = new FormData();
761+
formData.append("file", new Blob([output], {type : 'text/plain'}), fileName);
762+
formData.append("path", "TeachingTechYT");
763+
formData.append("select", "true");
764+
formData.append("print", "true");
765+
766+
fetch(url, {
767+
method: "POST",
768+
body: formData,
769+
headers: {
770+
'X-Api-Key': form.octoprint_key.value
771+
}
772+
})
773+
.then(response => {
774+
if (response.ok) {
775+
response.json().then(data => {
776+
if (data.print_started) {
777+
alert("Successfully uploaded and started print from " + fileName);
778+
} else {
779+
alert("Successfully uploaded, but print was not started from " + fileName);
780+
}
781+
});
782+
} else {
783+
alert("Failed to upload due to " + response.statusText);
784+
}
785+
})
786+
.catch((error) => {
787+
alert("Failed to upload due to an error. Possible causes:\n" +
788+
"- CORS not configured properly\n" +
789+
"- url does not start with `http://` or `https://`\n" +
790+
"\n" + error);
791+
});
729792
}

js/persist.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ function loadFormData(form) {
1717
element.tagName == "INPUT" && element.type == "checkbox" ||
1818
element.tagName == "INPUT" && element.type == "radio" ||
1919
element.tagName == "INPUT" && element.type == "text" ||
20+
element.tagName == "INPUT" && element.type == "password" ||
2021
element.tagName == "TEXTAREA" ||
2122
element.tagName == "SELECT"
2223
) {

0 commit comments

Comments
 (0)