diff --git a/Printer.py b/Printer.py
new file mode 100644
index 0000000..7abd16d
--- /dev/null
+++ b/Printer.py
@@ -0,0 +1,548 @@
+#
+# Copyright (C) 2021 Thomas Van Acker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see .""")
+#
+
+import serial
+import time
+import threading
+import math
+
+
+print("PrintBuddy V0.1")
+print("""
+Copyright (C) 2021 Thomas Van Acker
+
+This program comes with ABSOLUTELY NO WARRANTY.
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see .""")
+print("")
+
+# Static var init
+COMMANDS = {
+ "help":"List all commands with explanation",
+ "exit":"Disconnect from printer and exit",
+ "raw":"Send raw gcode commands",
+ "home":"Auto-home the machine",
+ "load":"Load a gcode file",
+ "add":"Manipulate the loaded gcode",
+ "print":"Print the loaded gcode",
+ "level":"Start bed leveling wizard",
+ "mesh":"Start mesh bed leveling wizard"
+}
+
+GCODE_FILCH_LAYER = ["G28 X Y", "M84", "M300 P3000", "M0", "M600", "M400", "G28 X Y", "G0 F1500"]
+
+# Function declarations
+def send(c, silent=False):
+ global s
+ if not silent:
+ print("%s"%c)
+ c += "\n"
+ s.write(c.encode("utf-8"))
+ while True:
+ r = s.readline().decode("utf-8").strip()
+ if not silent:
+ print(" > %s"%r)
+ if r[0:2] == "ok":
+ break
+
+def threadPrintInput():
+ # Checks for input from user during printing process
+ global abortPrint
+ while printing:
+ i = input()
+
+ if i == "stop" or i == "exit":
+ abortPrint = True
+ break
+
+def meshZ(X, Y):
+ # Interpolates values of mesh
+ x = X/300*(MESH_SIZE-1)
+ y = Y/300*(MESH_SIZE-1)
+
+ xmin = math.floor(x)
+ xmax = math.ceil(x)
+ ymin = math.floor(y)
+ ymax = math.ceil(y)
+
+ z0 = mesh[ymin][xmin] + (mesh[ymin][xmax]-mesh[ymin][xmin])*(x-xmin)
+ z1 = mesh[ymax][xmin] + (mesh[ymax][xmax]-mesh[ymax][xmin])*(x-xmin)
+
+ z = z0 + (z1-z0)*(y-ymin)
+ return z
+
+# Var init
+serialPort = "/dev/ttyUSB0"
+serialBaud = 115200
+
+gcodeRaw = ""
+gcodeLines = []
+gcodeLayers = 1
+printing = False
+abortPrint = False
+
+MESH_SIZE = 9 # Number of points of a side in the mesh.
+MESH_OFFSET = 1.00 # The distance above Z=0 where printbed is located. Mesh needs to be added to this number to get the absolute Z height.
+mesh = [[0 for _ in range(MESH_SIZE)] for __ in range(MESH_SIZE)]
+meshPositions = [["X%d Y%d"%(280/(MESH_SIZE-1)*x+10, 280/(MESH_SIZE-1)*y+10) for x in range(MESH_SIZE)] for y in range(MESH_SIZE)]
+
+levelingCornersPos = {0:"X10 Y45",1:"X10 Y260",2:"X280 Y260",3:"X280 Y45"}
+
+
+# Read mesh file
+print("Reading mesh file...")
+try:
+ f = open("mesh.txt", "r")
+ t = f.read()[:-1]
+ f.close()
+
+ lines = t.split("\n")
+ MESH_SIZE = int(lines[0])
+ mesh = [[0 for _ in range(MESH_SIZE)] for __ in range(MESH_SIZE)]
+ meshPositions = [["X%d Y%d"%(280/(MESH_SIZE-1)*x+10, 280/(MESH_SIZE-1)*y+10) for x in range(MESH_SIZE)] for y in range(MESH_SIZE)]
+
+ for i in range(MESH_SIZE*MESH_SIZE):
+ mesh[int(i/MESH_SIZE)][int(i%MESH_SIZE)] = float(lines[i+1])
+
+ print("Mesh loaded.")
+except Exception as e:
+ print("Couldn't read mesh file. Using default mesh.")
+ print(e)
+print("Current mesh:")
+for i in mesh:
+ for j in i:
+ print("{:5.2f}".format(j), end=" ")
+ print()
+
+# Connect to printer
+print("\nConnecting to printer...")
+s = serial.Serial(serialPort, serialBaud)
+time.sleep(1)
+s.write(b"\r\n\r\n") # Wake printer
+time.sleep(2)
+readBytes = s.inWaiting()
+r = s.read(readBytes).decode("utf-8")
+print(" > %s"%r)
+time.sleep(5)
+print("Connected!")
+
+# Start main loop
+while True:
+ print("\n# Please enter a command ('help' for command list)")
+ cmd = input()
+
+ if cmd == "help":
+ # List all commands
+ print("\nCOMMAND\t\tACTION")
+ for k in COMMANDS.keys():
+ print("%s\t\t%s"%(k, COMMANDS[k]))
+
+ elif cmd == "home":
+ # Home machine
+ send("G28", silent=True) #Auto-home
+ send("M84", silent=True) #Disable steppers
+
+ elif cmd == "raw":
+ # Send raw gcode commands
+ print("Entering raw mode. Proceed at your own risk. Type 'exit' to exit raw mode.")
+
+ while True:
+ print("\n# RAW: Please enter a gcode command (or 'exit' to exit)");
+ r = input()
+ if r == "exit":
+ break
+ send(r)
+
+ print("Exiting raw mode.")
+
+ elif cmd == "load":
+ # Load gcode file
+ print("# Please enter the path to the gcode file you want to load")
+ path = input()
+
+ # Try to open and parse file
+ try:
+ print("Trying to open file...")
+ f = open(path, "r")
+ print("Reading...")
+ gcodeRaw = f.read()[:-1]
+ f.close()
+ print("Parsing...")
+ gcodeLines = gcodeRaw.split("\n")
+
+ # Iterate through all lines to get info
+ gcodeLines = 0
+ for l in range(len(gcodeLines)):
+ line = gcodeLines[l]
+
+ if line[0] == ";":
+ # When comment
+ if line.startswith(";LAYER:"):
+ l = int(line[line.index(":") +1:])
+ if l > gcodeLayers:
+ gcodeLayers = l
+
+ print("#Layers: %d"%gcodeLayers)
+ print("%d lines"%len(gcodeLines))
+
+ print("File loaded! Use 'add' to manipulate this gcode.")
+ except Exception as e:
+ print("Couldn't read file:")
+ print(e)
+
+ # Reset gcode vars
+ gcodeRaw = ""
+ gcodeLines = []
+ gcodeLayers = 1
+
+ elif cmd == "add":
+ # Manipulate gcode
+
+ # Check if gcode present
+ if gcodeRaw == "" or len(gcodeLines) == 0:
+ print("No gcode loaded. Use 'load' to load gcode.")
+ continue
+
+ # Display all commands
+ print("COMMAND\t\tEXPLANATION")
+ print("exit\t\tReturn")
+ print("mesh\t\tEnable Mesh Bed Leveling")
+ print("filch\t\tFilament change at specific layer")
+ print("")
+ print("# Please enter one of the above actions.")
+
+ # Getting input
+ act = input()
+
+ if act == "exit":
+ print("Exiting.")
+ pass
+
+ elif act == "mesh":
+ # Add Mesh Bed Leveling
+ print("Recalculating Z with Mesh Bed Leveling...")
+ layerZ = 0
+ layerIndex = 0
+ for l in range(len(gcodeLines)):
+ line = gcodeLines[l]
+
+ # Check if comment
+ if line[0] == ";":
+ # Check if new layer
+ if line.startswith(";LAYER:"):
+ layerIndex = int(line[line.index(":") +1:])
+
+ if not (line.startswith("G0") or line.startswith("G1")):
+ continue
+
+ # When this is a movement line
+ tokens = line.split(" ")
+ indexX = -1
+ indexY = -1
+ indexZ = -1
+ for t in range(len(tokens)):
+ if tokens[t][0] == "X":
+ indexX = t
+ elif tokens[t][0] == "Y":
+ indexY = t
+ elif tokens[t][0] == "Z":
+ indexZ = t
+
+ # Check if Z is given
+ if not indexZ == -1:
+ # When Z is set -> save as layer height
+ layerZ = float(tokens[indexZ][1:])
+
+ # Add Z if X or Y are set
+ if indexX == -1 or indexY == -1:
+ continue
+
+ X = float(tokens[indexX][1:])
+ Y = float(tokens[indexY][1:])
+ Z = layerZ + MESH_OFFSET + (meshZ(X, Y)*max(0, float(10-layerIndex)/10.0) if layerIndex < 10 else 0)
+
+ # Add Z coordinate
+ tokens.append("Z{:.3f}".format(Z))
+ newLine = " ".join(tokens)
+ gcodeLines[l] = newLine
+ print("Done!")
+
+ elif act == "filch":
+ # Filament change at layer
+ layer = 0
+ while True:
+ # Ask for layer
+ print("# FILCH: At which layer do you want to change filament?")
+ l = input()
+
+ # Check if valid
+ try:
+ layer = int(l)
+
+ if layer > 0 and layer <= gcodeLayers:
+ break
+
+ print("Invalid.")
+ except:
+ print("Invalid.")
+
+ if layer == 0:
+ continue # exit
+
+ # Search for start of this layer
+ print("Searching for layer...")
+ success = False
+ for l in range(len(gcodeLines)):
+ line = gcodeLines[l]
+
+ if line[0] == ";":
+ if line.startswith(";LAYER:"):
+ thisLayer = int(line[line.find(":")+1:])
+
+ # Check if right layer
+ if thisLayer == layer:
+ # Add filch gcode
+ print("Adding gcode for filch...")
+ gcodeLines[l:l] = GCODE_FILCH_LAYER
+ success = True
+ break
+ print("Done." if success else "Couldn't find layer.")
+
+ else:
+ # When add action not found
+ print("Command not found.")
+
+ elif cmd == "print":
+ # Print loaded gcode
+ if len(gcodeLines) == 0:
+ print("No file loaded yet. Use 'load' to load gcode.")
+ else:
+ # Start print
+ printing = True
+ abortPrint = False
+ print("Print started. Type 'stop' at any time to abort the print.")
+ send("M75", silent=True) # Start timer
+
+ # Start thread to check for commands
+ threadInput = threading.Thread(target=threadPrintInput, daemon=True)
+ threadInput.start()
+
+ # Send gcode line by line to printer
+ for l in range(len(gcodeLines)):
+ line = gcodeLines[l]
+
+ # Check if needs to abort print
+ if abortPrint:
+ print("Aborting print!")
+ break
+
+ # Check if comment
+ if line[0] == ";":
+ # Check if new layer
+ if line.startswith(";LAYER:"):
+ layer = int(line[line.index(":") +1:])
+ print("Printing layer %d/%d"%(layer, gcodeLayers))
+ else:
+ # Send line to printer
+ send(line, silent=True)
+
+ # Stop input thread
+ printing = False
+
+ # Stop print
+ send("M104 S0", silent=True) # Hotend off
+ send("M140 S0", silent=True) # Bed off
+ send("M107", silent=True) # Fan off
+ send("M77", silent=True) # Stop timer
+ send("M31", silent=True) # Display time on lcd
+ send("G28 X Y", silent=True) # Home X and Y
+ send("G0 Y300 F1500", silent=True) # Move platform to user
+ send("M84", silent=True) # Disable steppers
+ send("M400", silent=True) # Wait for previous commands to finish
+ send("M300 P3000", silent=True) # Beep
+ print("Print done!")
+
+ elif cmd == "level":
+ # Normal leveling wizard
+ print("Starting leveling wizard...")
+ send("G28", silent=True) #Home
+ send("G0 F7500", silent=True) # Set feedrate
+
+ print("Please adjust the knob under the nozzle so that a piece of paper can slide under the nozzle with just a little bit of friction.")
+
+ # Start corner loop
+ i = 0
+ while True:
+ # Move to corner
+ print("Moving to corner %d..."%i)
+ send("G0 Z10", silent=True)
+ send("G0 %s"%levelingCornersPos[i], silent=True)
+ send("G0 Z0", silent=True)
+ send("M84", silent=True) #Disable steppers
+
+ # Prompt user
+ print("Press ENTER to move to next corner. Type 'exit' to exit wizard.")
+ r = input()
+
+ if r == "exit":
+ break
+
+ # Next corner
+ i = (i+1)%4
+
+ # End wizard
+ send("G0 F1500", silent=True) #Set slower feedrate
+ send("G28", silent=True) #Home
+ send("M84", silent=True) #Disable steppers
+
+
+ elif cmd == "mesh":
+ # Mesh leveling wizard
+ print("Starting mesh leveling wizard...")
+ send("G28", silent=True) #Home
+ send("G0 F7500", silent=True) # Set feedrate
+
+ print("\nSTEP 1: Normal leveling")
+ print("Please adjust the knob under the nozzle so that a piece of paper can slide under the nozzle with just a little bit of friction.")
+
+ # Start corner loop
+ i = 0
+ stop = False
+ while True:
+ # Move to corner
+ print("Moving to corner %d..."%i)
+ send("G0 Z10", silent=True)
+ send("G0 %s"%levelingCornersPos[i], silent=True)
+ send("G0 Z{:.2f}".format(MESH_OFFSET), silent=True)
+
+ # Prompt user
+ print("Press ENTER to move to next corner. Type 'next' to go to step 2. Type 'exit' to exit wizard.")
+ r = input()
+
+ if r == "exit":
+ stop = True
+ break
+ elif r == "next":
+ break
+
+ # Next corner
+ i = (i+1)%4
+
+ # Step 2: get mesh deltas
+ if not stop:
+ print("\nSTEP 2: Mesh leveling")
+ print("For every mesh point, lower the nozzle using the '+' and '-' buttons until the nozzle is at the right height. Then, enter 'next' to go to the next mesh point. Type 'exit' to exit the wizard.")
+
+ # Move through mesh
+ for y in range(MESH_SIZE):
+ for x in range(MESH_SIZE):
+ Z = 1.00 # Offset on top of MESH_OFFSET
+ print("\nMoving to mesh point x=%d, y=%d"%(x,y))
+ send("G0 Z10", silent=True)
+ send("G0 %s"%meshPositions[y][x], silent=True)
+ send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
+
+ # Input loop
+ stop = False
+ while True:
+ i = input()
+
+ if i == "+":
+ Z += 0.01
+ send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
+ elif i == "-":
+ Z -= 0.01
+ send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
+ elif i == "++":
+ Z += 0.1
+ send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
+ elif i == "--":
+ Z -= 0.1
+ send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
+ elif i == "+++":
+ Z += 0.5
+ send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
+ elif i == "---":
+ Z -= 0.5
+ send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
+ elif i == "exit":
+ stop = True
+ break
+ elif i == "next":
+ mesh[y][x] = Z
+ print("Mesh value saved (Z={:.3f})".format(Z))
+ break
+
+ # Check if needs to exit
+ if stop:
+ break
+ # Check if needs to exit
+ if stop:
+ break
+
+ # Print mesh
+ print("\nCurrent Mesh:")
+ for i in mesh:
+ for j in i:
+ print("{:6.3f}".format(j), end=" ")
+ print()
+
+
+ # Save mesh to file
+ print("Writing mesh to file...")
+ try:
+ t = ""
+ t += "%d\n"%MESH_SIZE
+ for y in range(MESH_SIZE):
+ for x in range(MESH_SIZE):
+ t += "{:.3f}\n".format(mesh[y][x])
+ f = open("mesh.txt", "w")
+ f.write(t)
+ f.close()
+ except Exception as e:
+ print("Couldn't write mesh to file.")
+ print(e)
+
+
+ # End wizard
+ send("G0 F1500", silent=True) #Set slower feedrate
+ send("G28", silent=True) #Home
+ send("M84", silent=True) #Disable steppers
+
+
+ elif cmd == "exit":
+ break
+ else:
+ print("Command not found. Enter 'help' to list all commands.")
+
+
+
+# Close serial
+print("Disconnecting from printer...")
+s.close()
+
+# End of script
+print("Thank you for using PrintBuddy!")
diff --git a/launch b/launch
new file mode 100755
index 0000000..33175cd
--- /dev/null
+++ b/launch
@@ -0,0 +1,3 @@
+#!/bin/bash
+cd $(dirname $0)
+python3 main.py
diff --git a/main.py b/main.py
index 7abd16d..d010269 100644
--- a/main.py
+++ b/main.py
@@ -1,548 +1,6 @@
-#
-# Copyright (C) 2021 Thomas Van Acker
-#
-# This program is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see .""")
-#
+from printserver import PrintServer
-import serial
-import time
-import threading
-import math
+# Start server
+server = PrintServer()
+server.start()
-
-print("PrintBuddy V0.1")
-print("""
-Copyright (C) 2021 Thomas Van Acker
-
-This program comes with ABSOLUTELY NO WARRANTY.
-
-This program is free software: you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation, either version 3 of the License, or (at your option) any later
-version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program. If not, see .""")
-print("")
-
-# Static var init
-COMMANDS = {
- "help":"List all commands with explanation",
- "exit":"Disconnect from printer and exit",
- "raw":"Send raw gcode commands",
- "home":"Auto-home the machine",
- "load":"Load a gcode file",
- "add":"Manipulate the loaded gcode",
- "print":"Print the loaded gcode",
- "level":"Start bed leveling wizard",
- "mesh":"Start mesh bed leveling wizard"
-}
-
-GCODE_FILCH_LAYER = ["G28 X Y", "M84", "M300 P3000", "M0", "M600", "M400", "G28 X Y", "G0 F1500"]
-
-# Function declarations
-def send(c, silent=False):
- global s
- if not silent:
- print("%s"%c)
- c += "\n"
- s.write(c.encode("utf-8"))
- while True:
- r = s.readline().decode("utf-8").strip()
- if not silent:
- print(" > %s"%r)
- if r[0:2] == "ok":
- break
-
-def threadPrintInput():
- # Checks for input from user during printing process
- global abortPrint
- while printing:
- i = input()
-
- if i == "stop" or i == "exit":
- abortPrint = True
- break
-
-def meshZ(X, Y):
- # Interpolates values of mesh
- x = X/300*(MESH_SIZE-1)
- y = Y/300*(MESH_SIZE-1)
-
- xmin = math.floor(x)
- xmax = math.ceil(x)
- ymin = math.floor(y)
- ymax = math.ceil(y)
-
- z0 = mesh[ymin][xmin] + (mesh[ymin][xmax]-mesh[ymin][xmin])*(x-xmin)
- z1 = mesh[ymax][xmin] + (mesh[ymax][xmax]-mesh[ymax][xmin])*(x-xmin)
-
- z = z0 + (z1-z0)*(y-ymin)
- return z
-
-# Var init
-serialPort = "/dev/ttyUSB0"
-serialBaud = 115200
-
-gcodeRaw = ""
-gcodeLines = []
-gcodeLayers = 1
-printing = False
-abortPrint = False
-
-MESH_SIZE = 9 # Number of points of a side in the mesh.
-MESH_OFFSET = 1.00 # The distance above Z=0 where printbed is located. Mesh needs to be added to this number to get the absolute Z height.
-mesh = [[0 for _ in range(MESH_SIZE)] for __ in range(MESH_SIZE)]
-meshPositions = [["X%d Y%d"%(280/(MESH_SIZE-1)*x+10, 280/(MESH_SIZE-1)*y+10) for x in range(MESH_SIZE)] for y in range(MESH_SIZE)]
-
-levelingCornersPos = {0:"X10 Y45",1:"X10 Y260",2:"X280 Y260",3:"X280 Y45"}
-
-
-# Read mesh file
-print("Reading mesh file...")
-try:
- f = open("mesh.txt", "r")
- t = f.read()[:-1]
- f.close()
-
- lines = t.split("\n")
- MESH_SIZE = int(lines[0])
- mesh = [[0 for _ in range(MESH_SIZE)] for __ in range(MESH_SIZE)]
- meshPositions = [["X%d Y%d"%(280/(MESH_SIZE-1)*x+10, 280/(MESH_SIZE-1)*y+10) for x in range(MESH_SIZE)] for y in range(MESH_SIZE)]
-
- for i in range(MESH_SIZE*MESH_SIZE):
- mesh[int(i/MESH_SIZE)][int(i%MESH_SIZE)] = float(lines[i+1])
-
- print("Mesh loaded.")
-except Exception as e:
- print("Couldn't read mesh file. Using default mesh.")
- print(e)
-print("Current mesh:")
-for i in mesh:
- for j in i:
- print("{:5.2f}".format(j), end=" ")
- print()
-
-# Connect to printer
-print("\nConnecting to printer...")
-s = serial.Serial(serialPort, serialBaud)
-time.sleep(1)
-s.write(b"\r\n\r\n") # Wake printer
-time.sleep(2)
-readBytes = s.inWaiting()
-r = s.read(readBytes).decode("utf-8")
-print(" > %s"%r)
-time.sleep(5)
-print("Connected!")
-
-# Start main loop
-while True:
- print("\n# Please enter a command ('help' for command list)")
- cmd = input()
-
- if cmd == "help":
- # List all commands
- print("\nCOMMAND\t\tACTION")
- for k in COMMANDS.keys():
- print("%s\t\t%s"%(k, COMMANDS[k]))
-
- elif cmd == "home":
- # Home machine
- send("G28", silent=True) #Auto-home
- send("M84", silent=True) #Disable steppers
-
- elif cmd == "raw":
- # Send raw gcode commands
- print("Entering raw mode. Proceed at your own risk. Type 'exit' to exit raw mode.")
-
- while True:
- print("\n# RAW: Please enter a gcode command (or 'exit' to exit)");
- r = input()
- if r == "exit":
- break
- send(r)
-
- print("Exiting raw mode.")
-
- elif cmd == "load":
- # Load gcode file
- print("# Please enter the path to the gcode file you want to load")
- path = input()
-
- # Try to open and parse file
- try:
- print("Trying to open file...")
- f = open(path, "r")
- print("Reading...")
- gcodeRaw = f.read()[:-1]
- f.close()
- print("Parsing...")
- gcodeLines = gcodeRaw.split("\n")
-
- # Iterate through all lines to get info
- gcodeLines = 0
- for l in range(len(gcodeLines)):
- line = gcodeLines[l]
-
- if line[0] == ";":
- # When comment
- if line.startswith(";LAYER:"):
- l = int(line[line.index(":") +1:])
- if l > gcodeLayers:
- gcodeLayers = l
-
- print("#Layers: %d"%gcodeLayers)
- print("%d lines"%len(gcodeLines))
-
- print("File loaded! Use 'add' to manipulate this gcode.")
- except Exception as e:
- print("Couldn't read file:")
- print(e)
-
- # Reset gcode vars
- gcodeRaw = ""
- gcodeLines = []
- gcodeLayers = 1
-
- elif cmd == "add":
- # Manipulate gcode
-
- # Check if gcode present
- if gcodeRaw == "" or len(gcodeLines) == 0:
- print("No gcode loaded. Use 'load' to load gcode.")
- continue
-
- # Display all commands
- print("COMMAND\t\tEXPLANATION")
- print("exit\t\tReturn")
- print("mesh\t\tEnable Mesh Bed Leveling")
- print("filch\t\tFilament change at specific layer")
- print("")
- print("# Please enter one of the above actions.")
-
- # Getting input
- act = input()
-
- if act == "exit":
- print("Exiting.")
- pass
-
- elif act == "mesh":
- # Add Mesh Bed Leveling
- print("Recalculating Z with Mesh Bed Leveling...")
- layerZ = 0
- layerIndex = 0
- for l in range(len(gcodeLines)):
- line = gcodeLines[l]
-
- # Check if comment
- if line[0] == ";":
- # Check if new layer
- if line.startswith(";LAYER:"):
- layerIndex = int(line[line.index(":") +1:])
-
- if not (line.startswith("G0") or line.startswith("G1")):
- continue
-
- # When this is a movement line
- tokens = line.split(" ")
- indexX = -1
- indexY = -1
- indexZ = -1
- for t in range(len(tokens)):
- if tokens[t][0] == "X":
- indexX = t
- elif tokens[t][0] == "Y":
- indexY = t
- elif tokens[t][0] == "Z":
- indexZ = t
-
- # Check if Z is given
- if not indexZ == -1:
- # When Z is set -> save as layer height
- layerZ = float(tokens[indexZ][1:])
-
- # Add Z if X or Y are set
- if indexX == -1 or indexY == -1:
- continue
-
- X = float(tokens[indexX][1:])
- Y = float(tokens[indexY][1:])
- Z = layerZ + MESH_OFFSET + (meshZ(X, Y)*max(0, float(10-layerIndex)/10.0) if layerIndex < 10 else 0)
-
- # Add Z coordinate
- tokens.append("Z{:.3f}".format(Z))
- newLine = " ".join(tokens)
- gcodeLines[l] = newLine
- print("Done!")
-
- elif act == "filch":
- # Filament change at layer
- layer = 0
- while True:
- # Ask for layer
- print("# FILCH: At which layer do you want to change filament?")
- l = input()
-
- # Check if valid
- try:
- layer = int(l)
-
- if layer > 0 and layer <= gcodeLayers:
- break
-
- print("Invalid.")
- except:
- print("Invalid.")
-
- if layer == 0:
- continue # exit
-
- # Search for start of this layer
- print("Searching for layer...")
- success = False
- for l in range(len(gcodeLines)):
- line = gcodeLines[l]
-
- if line[0] == ";":
- if line.startswith(";LAYER:"):
- thisLayer = int(line[line.find(":")+1:])
-
- # Check if right layer
- if thisLayer == layer:
- # Add filch gcode
- print("Adding gcode for filch...")
- gcodeLines[l:l] = GCODE_FILCH_LAYER
- success = True
- break
- print("Done." if success else "Couldn't find layer.")
-
- else:
- # When add action not found
- print("Command not found.")
-
- elif cmd == "print":
- # Print loaded gcode
- if len(gcodeLines) == 0:
- print("No file loaded yet. Use 'load' to load gcode.")
- else:
- # Start print
- printing = True
- abortPrint = False
- print("Print started. Type 'stop' at any time to abort the print.")
- send("M75", silent=True) # Start timer
-
- # Start thread to check for commands
- threadInput = threading.Thread(target=threadPrintInput, daemon=True)
- threadInput.start()
-
- # Send gcode line by line to printer
- for l in range(len(gcodeLines)):
- line = gcodeLines[l]
-
- # Check if needs to abort print
- if abortPrint:
- print("Aborting print!")
- break
-
- # Check if comment
- if line[0] == ";":
- # Check if new layer
- if line.startswith(";LAYER:"):
- layer = int(line[line.index(":") +1:])
- print("Printing layer %d/%d"%(layer, gcodeLayers))
- else:
- # Send line to printer
- send(line, silent=True)
-
- # Stop input thread
- printing = False
-
- # Stop print
- send("M104 S0", silent=True) # Hotend off
- send("M140 S0", silent=True) # Bed off
- send("M107", silent=True) # Fan off
- send("M77", silent=True) # Stop timer
- send("M31", silent=True) # Display time on lcd
- send("G28 X Y", silent=True) # Home X and Y
- send("G0 Y300 F1500", silent=True) # Move platform to user
- send("M84", silent=True) # Disable steppers
- send("M400", silent=True) # Wait for previous commands to finish
- send("M300 P3000", silent=True) # Beep
- print("Print done!")
-
- elif cmd == "level":
- # Normal leveling wizard
- print("Starting leveling wizard...")
- send("G28", silent=True) #Home
- send("G0 F7500", silent=True) # Set feedrate
-
- print("Please adjust the knob under the nozzle so that a piece of paper can slide under the nozzle with just a little bit of friction.")
-
- # Start corner loop
- i = 0
- while True:
- # Move to corner
- print("Moving to corner %d..."%i)
- send("G0 Z10", silent=True)
- send("G0 %s"%levelingCornersPos[i], silent=True)
- send("G0 Z0", silent=True)
- send("M84", silent=True) #Disable steppers
-
- # Prompt user
- print("Press ENTER to move to next corner. Type 'exit' to exit wizard.")
- r = input()
-
- if r == "exit":
- break
-
- # Next corner
- i = (i+1)%4
-
- # End wizard
- send("G0 F1500", silent=True) #Set slower feedrate
- send("G28", silent=True) #Home
- send("M84", silent=True) #Disable steppers
-
-
- elif cmd == "mesh":
- # Mesh leveling wizard
- print("Starting mesh leveling wizard...")
- send("G28", silent=True) #Home
- send("G0 F7500", silent=True) # Set feedrate
-
- print("\nSTEP 1: Normal leveling")
- print("Please adjust the knob under the nozzle so that a piece of paper can slide under the nozzle with just a little bit of friction.")
-
- # Start corner loop
- i = 0
- stop = False
- while True:
- # Move to corner
- print("Moving to corner %d..."%i)
- send("G0 Z10", silent=True)
- send("G0 %s"%levelingCornersPos[i], silent=True)
- send("G0 Z{:.2f}".format(MESH_OFFSET), silent=True)
-
- # Prompt user
- print("Press ENTER to move to next corner. Type 'next' to go to step 2. Type 'exit' to exit wizard.")
- r = input()
-
- if r == "exit":
- stop = True
- break
- elif r == "next":
- break
-
- # Next corner
- i = (i+1)%4
-
- # Step 2: get mesh deltas
- if not stop:
- print("\nSTEP 2: Mesh leveling")
- print("For every mesh point, lower the nozzle using the '+' and '-' buttons until the nozzle is at the right height. Then, enter 'next' to go to the next mesh point. Type 'exit' to exit the wizard.")
-
- # Move through mesh
- for y in range(MESH_SIZE):
- for x in range(MESH_SIZE):
- Z = 1.00 # Offset on top of MESH_OFFSET
- print("\nMoving to mesh point x=%d, y=%d"%(x,y))
- send("G0 Z10", silent=True)
- send("G0 %s"%meshPositions[y][x], silent=True)
- send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
-
- # Input loop
- stop = False
- while True:
- i = input()
-
- if i == "+":
- Z += 0.01
- send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
- elif i == "-":
- Z -= 0.01
- send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
- elif i == "++":
- Z += 0.1
- send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
- elif i == "--":
- Z -= 0.1
- send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
- elif i == "+++":
- Z += 0.5
- send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
- elif i == "---":
- Z -= 0.5
- send("G0 Z{:.3f}".format(Z+MESH_OFFSET), silent=True)
- elif i == "exit":
- stop = True
- break
- elif i == "next":
- mesh[y][x] = Z
- print("Mesh value saved (Z={:.3f})".format(Z))
- break
-
- # Check if needs to exit
- if stop:
- break
- # Check if needs to exit
- if stop:
- break
-
- # Print mesh
- print("\nCurrent Mesh:")
- for i in mesh:
- for j in i:
- print("{:6.3f}".format(j), end=" ")
- print()
-
-
- # Save mesh to file
- print("Writing mesh to file...")
- try:
- t = ""
- t += "%d\n"%MESH_SIZE
- for y in range(MESH_SIZE):
- for x in range(MESH_SIZE):
- t += "{:.3f}\n".format(mesh[y][x])
- f = open("mesh.txt", "w")
- f.write(t)
- f.close()
- except Exception as e:
- print("Couldn't write mesh to file.")
- print(e)
-
-
- # End wizard
- send("G0 F1500", silent=True) #Set slower feedrate
- send("G28", silent=True) #Home
- send("M84", silent=True) #Disable steppers
-
-
- elif cmd == "exit":
- break
- else:
- print("Command not found. Enter 'help' to list all commands.")
-
-
-
-# Close serial
-print("Disconnecting from printer...")
-s.close()
-
-# End of script
-print("Thank you for using PrintBuddy!")
diff --git a/pageresolver.py b/pageresolver.py
new file mode 100644
index 0000000..9aa3368
--- /dev/null
+++ b/pageresolver.py
@@ -0,0 +1,6 @@
+
+def resolve(path):
+ # Returns a resultCode and webpage for this path
+ page = "
Hello, world!
"
+ return (200, page)
+
diff --git a/printserver.py b/printserver.py
new file mode 100644
index 0000000..d7b9108
--- /dev/null
+++ b/printserver.py
@@ -0,0 +1,17 @@
+from http.server import HTTPServer
+from webserver import WebServer
+
+# Server config
+SERVER_HOST = "localhost"
+SERVER_PORT = 4000
+
+
+class PrintServer(object):
+ def __init__(self):
+ self.server = HTTPServer((SERVER_HOST, SERVER_PORT), WebServer)
+
+ def start(self):
+ # Start serving pages
+ self.server.serve_forever()
+ self.server.server_close()
+
diff --git a/webserver.py b/webserver.py
new file mode 100644
index 0000000..9dc065a
--- /dev/null
+++ b/webserver.py
@@ -0,0 +1,14 @@
+from http.server import BaseHTTPRequestHandler
+import pageresolver
+
+class WebServer(BaseHTTPRequestHandler):
+ def do_GET(self):
+ # Create page contents
+ (responseCode, page) = pageresolver.resolve(self.path)
+
+ # Return page
+ self.send_response(responseCode)
+ self.send_header("Content-type", "text/html")
+ self.end_headers()
+ self.wfile.write(bytes(page, "utf-8"))
+