diff --git a/WifiConnection.py b/WifiConnection.py index 5d1a4a6c9c..535971e840 100644 --- a/WifiConnection.py +++ b/WifiConnection.py @@ -1,11 +1,10 @@ from UM.OutputDevice.OutputDevice import OutputDevice from UM.OutputDevice import OutputDeviceError import threading -import http.client as httpclient -import urllib import json import time import base64 +import requests from . import HttpUploadDataStream from UM.i18n import i18nCatalog @@ -24,8 +23,13 @@ class WifiConnection(OutputDevice, SignalEmitter): self._file = None self._do_update = True self._thread = None - self._state = None + + self._json_printer_state = None + self._is_connected = False + + self._api_version = "1" + self._api_prefix = "/api/v" + self._api_version + "/" self.connect() self.setName(address) self.setShortDescription(i18n_catalog.i18nc("@action:button", "Print with WIFI")) @@ -37,23 +41,25 @@ class WifiConnection(OutputDevice, SignalEmitter): def isConnected(self): return self._is_connected + ## Set the connection state of this connection. + # Although we use a restfull API, we do poll the api to check if the machine is still responding. def setConnectionState(self, state): - print("setting connection state: " , self._address, " " , state) if state != self._is_connected: + Logger.log("i", "setting connection state of %s to %s " %(self._address, state)) self._is_connected = state self.connectionStateChanged.emit(self._address) else: - self._is_connected = state + self._is_connected = state def _update(self): while self._thread: - state_reply = self._httpRequest('GET', '/api/v1/printer/state') - if state_reply is not None: - self._state = state_reply + self.setConnectionState(True) + reply = self._httpGet("printer") + if reply.status_code == 200: + self._json_printer_state = reply.json() if not self._is_connected: self.setConnectionState(True) else: - self._state = {'state': 'CONNECTION_ERROR'} self.setConnectionState(False) time.sleep(1) @@ -61,11 +67,11 @@ class WifiConnection(OutputDevice, SignalEmitter): self._do_update = False self._is_connected = False - def requestWrite(self, node): + def requestWrite(self, node, file_name = None): self._file = getattr( Application.getInstance().getController().getScene(), "gcode_list") self.startPrint() - #Open the active connection to the printer so we can send commands + ## Start the polling thread. def connect(self): if self._thread is None: self._do_update = True @@ -78,65 +84,22 @@ class WifiConnection(OutputDevice, SignalEmitter): def startPrint(self): try: - result = self._httpRequest('POST', '/api/v1/printer/print_upload', {'print_name': 'Print from Cura', 'parameters':''}, {'file': ('file.gcode', self._file)}) - print(result.get('success',False)) - #result = self._httpRequest('POST', '/api/v1/printer/print_upload', {'print_name': 'Print from Cura'}) + result = self._httpPost("print_job", self._file) except Exception as e: - Logger.log('e' , 'An exception occured in wifi connection: ' , e) + Logger.log("e" , "An exception occured in wifi connection: %s" % str(e)) - def _httpRequest(self, method, path, post_data = None, files = None): + def _httpGet(self, path): + return requests.get("http://" + self._address + self._api_prefix + path) + + def _httpPost(self, path, file_data): with self._http_lock: - self._http_connection = httpclient.HTTPConnection(self._address, timeout = 30) - try: - if files is not None: - boundary = 'wL36Yn8afVp8Ag7AmP8qZ0SA4n1v9T' - s = HttpUploadDataStream.HttpUploadDataStream() - for k, v in files.items(): - filename = v[0] - file_contents = v[1] - s.write('--%s\r\n' % (boundary)) - s.write('Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (k, filename)) - s.write('Content-Type: application/octet-stream\r\n') - s.write('Content-Transfer-Encoding: binary\r\n') - s.write('\r\n') + 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)} - if file_contents is not None: - for line in file_contents: - s.write(str(line)) - - s.write('\r\n') - - for k, v in post_data.items(): - s.write('--%s\r\n' % (boundary)) - s.write('Content-Disposition: form-data; name="%s"\r\n' % (k)) - s.write('\r\n') - s.write(str(v)) - s.write('\r\n') - s.write('--%s--\r\n' % (boundary)) - - self._http_connection.request(method, path, s, {"Content-type": "multipart/form-data; boundary=%s" % (boundary), "Content-Length": len(s)}) - elif post_data is not None: - - self._http_connection.request(method, path, urllib.urlencode(post_data), {"Content-type": "application/x-www-form-urlencoded", "User-Agent": "Cura Doodle3D connection"}) - else: - self._http_connection.request(method, path, headers={"Content-type": "application/x-www-form-urlencoded", "User-Agent": "Cura Doodle3D connection"}) - except IOError: - self._http_connection.close() - return None - except Exception as e: - self._http_connection.close() - return None - - try: - response = self._http_connection.getresponse() - response_text = response.read() - except IOError: - self._http_connection.close() - return None - try: - response = json.loads(response_text.decode("utf-8")) - except ValueError: - self._http_connection.close() - return None - self._http_connection.close() - return response + return requests.post("http://" + self._address + self._api_prefix + path, files = files_dict) \ No newline at end of file diff --git a/WifiOutputDevicePlugin.py b/WifiOutputDevicePlugin.py index e01c078cde..e9b1848138 100644 --- a/WifiOutputDevicePlugin.py +++ b/WifiOutputDevicePlugin.py @@ -14,24 +14,24 @@ class WifiOutputDevicePlugin(OutputDevicePlugin, SignalEmitter): addConnectionSignal = Signal() + ## Start looking for devices on network. def start(self): self._browser = ServiceBrowser(Zeroconf(), u'_ultimaker._tcp.local.', [self._onServiceChanged]) + ## Stop looking for devices on network. def stop(self): self._zero_conf.close() ## Because the model needs to be created in the same thread as the QMLEngine, we use a signal. def addConnection(self, name, address, properties): - connection = WifiConnection.WifiConnection(address, properties) - connection.connect() - self._connections[address] = connection - if address == "10.180.1.23": #DEBUG - #if address == "10.180.0.249": #DEBUG - connection.startPrint() + if address == "10.180.1.30": #DEBUG + connection = WifiConnection.WifiConnection(address, properties) + connection.connect() + self._connections[address] = connection connection.connectionStateChanged.connect(self._onPrinterConnectionStateChanged) def _onPrinterConnectionStateChanged(self, address): - print(self._connections[address].isConnected()) + print("_onPrinterConnectionStateChanged" , self._connections[address].isConnected()) if self._connections[address].isConnected(): self.getOutputDeviceManager().addOutputDevice(self._connections[address]) else: @@ -49,5 +49,6 @@ class WifiOutputDevicePlugin(OutputDevicePlugin, SignalEmitter): self.addConnectionSignal.emit(str(name), address, info.properties) elif state_change == ServiceStateChange.Removed: - print("Device disconnected") - #print("HERP DERP") + info = zeroconf.get_service_info(service_type, name) + address = '.'.join(map(lambda n: str(n), info.address)) + print("Device disconnected: ", address)