Cura/NetworkPrinterOutputDevice.py
Jaime van Kessel f9bf54348d Head position is now saved
CURA-49
2016-04-19 15:35:56 +02:00

150 lines
6.3 KiB
Python

import threading
import time
import requests
from UM.i18n import i18nCatalog
from UM.Application import Application
from UM.Logger import Logger
from UM.Message import Message
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState
i18n_catalog = i18nCatalog("cura")
## Network connected (wifi / lan) printer that uses the Ultimaker API
class NetworkPrinterOutputDevice(PrinterOutputDevice):
def __init__(self, key, address, info):
super().__init__(key)
self._address = address
self._key = key
self._info = info
self._http_lock = threading.Lock()
self._http_connection = None
self._file = None
self._update_thread = None
self._json_printer_state = None
self._num_extruders = 2
self._api_version = "1"
self._api_prefix = "/api/v" + self._api_version + "/"
self.setName(key)
self.setShortDescription(i18n_catalog.i18nc("@action:button", "Print with WIFI"))
self.setDescription(i18n_catalog.i18nc("@info:tooltip", "Print with WIFI"))
self.setIconName("print")
self._progress_message = None
self._error_message = None
def getKey(self):
return self._key
def _update(self):
Logger.log("d", "Update thread of printer with key %s and ip %s started", self._key, self._address)
while self.isConnected():
try:
printer_reply = self._httpGet("printer")
if printer_reply.status_code == 200:
self._json_printer_state = printer_reply.json()
try:
self._spliceJSONData()
except:
# issues with json parsing should not break by definition TODO: Check in what cases it should fail.
pass
if self._connection_state == ConnectionState.connecting:
# First successful response, so we are now "connected"
self.setConnectionState(ConnectionState.connected)
else:
Logger.log("w", "Got http status code %s while trying to request data.", printer_reply.status_code)
self.setConnectionState(ConnectionState.error)
print_job_reply = self._httpGet("print_job")
if print_job_reply.status_code != 404:
self.setProgress(print_job_reply.json()["progress"])
else:
self.setProgress(0)
except Exception as e:
self.setConnectionState(ConnectionState.error)
Logger.log("w", "Exception occured while connecting; %s", str(e))
time.sleep(2) # Poll every second for printer state.
Logger.log("d", "Update thread of printer with key %s and ip %s stopped with state: %s", self._key, self._address, self._connection_state)
## Convenience function that gets information from the recieved json data and converts it to the right internal
# values / variables
def _spliceJSONData(self):
# Check for hotend temperatures
for index in range(0, self._num_extruders - 1):
temperature = self._json_printer_state["heads"][0]["extruders"][index]["hotend"]["temperature"]["current"]
self._setHotendTemperature(index, temperature)
bed_temperature = self._json_printer_state["bed"]["temperature"]
self._setBedTemperature(bed_temperature)
head_x = self._json_printer_state["heads"][0]["position"]["x"]
head_y = self._json_printer_state["heads"][0]["position"]["y"]
head_z = self._json_printer_state["heads"][0]["position"]["z"]
self._updateHeadPosition(head_x, head_y, head_z)
def close(self):
self._connection_state == ConnectionState.closed
if self._update_thread != None:
self._update_thread.join()
self._update_thread = None
def requestWrite(self, node, file_name = None, filter_by_machine = False):
self._file = getattr(Application.getInstance().getController().getScene(), "gcode_list")
self.startPrint()
def isConnected(self):
return self._connection_state != ConnectionState.closed and self._connection_state != ConnectionState.error
## Start the polling thread.
def connect(self):
if self._update_thread is None:
self.setConnectionState(ConnectionState.connecting)
self._update_thread = threading.Thread(target = self._update)
self._update_thread.daemon = True
self._update_thread.start()
def getCameraImage(self):
pass #Do Nothing
def startPrint(self):
if self._progress != 0:
self._error_message = Message(i18n_catalog.i18nc("@info:status", "Printer is still printing. Unable to start a new job."))
self._error_message.show()
return
try:
self._progress_message = Message(i18n_catalog.i18nc("@info:status", "Sending data to printer"), 0, False, -1)
self._progress_message.show()
#TODO: Create a job that handles this! (As it currently locks up UI)
result = self._httpPost("print_job", self._file)
self._progress_message.hide()
if result.status_code == 200:
pass
except IOError:
self._progress_message.hide()
self._error_message = Message(i18n_catalog.i18nc("@info:status", "Unable to send data to printer. Is another job still active?"))
self._error_message.show()
except Exception as e:
self._progress_message.hide()
Logger.log("e" , "An exception occured in wifi connection: %s" % str(e))
def _httpGet(self, path):
return requests.get("http://" + self._address + self._api_prefix + path)
def _httpPost(self, path, file_data):
with self._http_lock:
files_dict = {}
if isinstance(file_data, list): # in case a list with strings is sent
single_string_file_data = ""
for line in file_data:
single_string_file_data += line
files_dict = {"file":("test.gcode", single_string_file_data)}
else:
files_dict = {"file":("test.gcode", file_data)}
return requests.post("http://" + self._address + self._api_prefix + path, files = files_dict)