def _octoprintThread(self): self._waitDelay = 0 while True: updated = self._config.updateConfigFromFile() if updated: for printer in self._config.getPrinters(): connection = self._connectionMap[printer.getKey()] if not connection: self._addPrinter(printer) else: connection.setApiKey(printer.getApiKey()) if self._config.getDiscovery(): for ssdpResponse in discover("ssdp:all"): try: if ssdpResponse.usn not in self._ignored and ssdpResponse.usn not in self._connectionMap.keys(): scheme, host, port, path = self._parseLocation(ssdpResponse.location) httpResponse = OctoPrintHttpClient(scheme, host, port, "", "xml").request("GET", path) if not httpResponse.isOk() or httpResponse.body is None: self._ignored.append(ssdpResponse.usn) continue manufacturer = httpResponse.body.find("{urn:schemas-upnp-org:device-1-0}device/{urn:schemas-upnp-org:device-1-0}manufacturer") if manufacturer is not None: manufacturer = manufacturer.text presentationURL = httpResponse.body.find("{urn:schemas-upnp-org:device-1-0}device/{urn:schemas-upnp-org:device-1-0}presentationURL") if presentationURL is not None: presentationURL = presentationURL.text friendlyName = httpResponse.body.find("{urn:schemas-upnp-org:device-1-0}device/{urn:schemas-upnp-org:device-1-0}friendlyName") if friendlyName is not None: friendlyName = friendlyName.text if manufacturer and presentationURL and "octoprint" in manufacturer.lower(): scheme, host, port, path = self._parseLocation(presentationURL) printer = OctoPrintPrinter(friendlyName, scheme, host, port, path, None, ssdpResponse.usn) self._config.updatePrinter(printer) self._addPrinter(printer) else: self._ignored.append(ssdpResponse.usn) time.sleep(0.01) except: print "Response Error: ({}:{})".format(ssdpResponse.usn, ssdpResponse.location) traceback.print_exc() self._ignored.append(ssdpResponse.usn) # Delay a bit more after every request. This so we do not stress the ssdp services too much if self._waitDelay < 10: self._waitDelay += 1 time.sleep(self._waitDelay * 30)
def __init__(self, key, name, scheme, host, port, path, apiKey, group): super(OctoPrintPrinterConnection, self).__init__(name) print "{} Connection created: {}://{}:{}{}".format(name, scheme, host, port, path) self._group = group self._key = key self._httpClient = OctoPrintHttpClient(scheme, host, port, path, "json") if apiKey: self.setApiKey(apiKey) self._isAvailable = False self._printing = False self._jobFileName = None self._progress = 0.0; self._printFilename = None self._hotendTemperature = [None] * 4 self._bedTemperature = None self._needsAuthorization = False self._errorCount = 0 self._interruptSleep = False self.checkThread = threading.Thread(target=self._octoprintThread) self.checkThread.daemon = True self.checkThread.start() self.getApiKeyThread = threading.Thread(target=self._octoprintGetApiKeyThread) self.getApiKeyThread.daemon = True self.getApiKeyThread.start()
def __init__(self, key, name, scheme, host, port, path, apiKey, group): super(OctoPrintPrinterConnection, self).__init__(name) print "{} Connection created: {}://{}:{}{}".format( name, scheme, host, port, path) self._group = group self._key = key self._httpClient = OctoPrintHttpClient(scheme, host, port, path, "json") if apiKey: self.setApiKey(apiKey) self._isAvailable = False self._printing = False self._jobFileName = None self._progress = 0.0 self._printFilename = None self._hotendTemperature = [None] * 4 self._bedTemperature = None self._needsAuthorization = False self._errorCount = 0 self._interruptSleep = False self.checkThread = threading.Thread(target=self._octoprintThread) self.checkThread.daemon = True self.checkThread.start() self.getApiKeyThread = threading.Thread( target=self._octoprintGetApiKeyThread) self.getApiKeyThread.daemon = True self.getApiKeyThread.start()
class OctoPrintPrinterConnection(printerConnectionBase.printerConnectionBase): """ Class to connect and print files with the OctoPrint Auto-detects if the OctoPrint box is available and handles communication with the OctoPrint API """ def __init__(self, key, name, scheme, host, port, path, apiKey, group): super(OctoPrintPrinterConnection, self).__init__(name) print "{} Connection created: {}://{}:{}{}".format(name, scheme, host, port, path) self._group = group self._key = key self._httpClient = OctoPrintHttpClient(scheme, host, port, path, "json") if apiKey: self.setApiKey(apiKey) self._isAvailable = False self._printing = False self._jobFileName = None self._progress = 0.0; self._printFilename = None self._hotendTemperature = [None] * 4 self._bedTemperature = None self._needsAuthorization = False self._errorCount = 0 self._interruptSleep = False self.checkThread = threading.Thread(target=self._octoprintThread) self.checkThread.daemon = True self.checkThread.start() self.getApiKeyThread = threading.Thread(target=self._octoprintGetApiKeyThread) self.getApiKeyThread.daemon = True self.getApiKeyThread.start() def setApiKey(self, apiKey): self._httpClient.addHeader("X-Api-Key", apiKey) #Load the file into memory for printing. def loadGCodeDataForFilename(self, dataStream, filename): if self._printing: return False self._printFilename = filename response = self._httpClient.request("POST", "/api/files/local", dataStream, filename) if response.isOk(): self._printFilename = filename self._doCallback() if response.isOk(): return True else: return False #Start printing the previously loaded file def startPrint(self): if self._printing or not self._printFilename: return response = self._httpClient.request("POST", "/api/files/local/{}".format(self._printFilename), {"command": "select", "print": True}) if response.isOk(): self._printing = True self._interruptSleep = True else: self._printing = False self._progress = 0.0 self._printFilename = None #Abort the previously loaded print file def cancelPrint(self): if not self._printing: return response = self._httpClient.request('POST', '/api/job', {'command': 'cancel'}) if response.isOk(): self._printing = False def isPrinting(self): return self._printing #Amount of progression of the current print file. 0.0 to 1.0 def getPrintProgress(self): return self._progress or 0.0 # Return if the printer with this connection type is available def isAvailable(self): return self._isAvailable #Are we able to send a direct coammand with sendCommand at this moment in time. def isAbleToSendDirectCommand(self): #The send command appears to be in flux, so not going to support for now return False #Directly send a command to the printer. def sendCommand(self, command): return # Get the connection status string. This is displayed to the user and can be used to communicate # various information to the user. def getStatusString(self): if not self._isAvailable: return "OctoPrint is not found, or does not have a printer connected currently" elif self._printing: return "Currently printing {}".format(self._jobFileName) else: return "OctoPrint is ready to print" #Get the temperature of an extruder, returns None is no temperature is known for this extruder def getTemperature(self, extruder): return self._hotendTemperature[extruder] #Get the temperature of the heated bed, returns None is no temperature is known for the heated bed def getBedTemperature(self): return self._bedTemperature def _octoprintThread(self): while True: response = self._httpClient.request('GET', '/api/job') if response.isUnauthorized(): self._needsAuthorization = True self._sleep(60) continue if not response.isOk(): # No API, wait 5 seconds before looking for OctoPrint again. # API gave back an error # OctoPrint could also be offline, if we reach a high enough errorCount then assume it is gone. self._errorCount += 1 if self._errorCount > 10: if self._isAvailable: self._printing = False self._isAvailable = False self._doCallback() self._sleep(15) self._group.remove(self._key) return else: self._sleep(3) continue if response.body['state'] == 'Closed' or response.body['state'] == "Connecting": # No printer connected, we do not have a printer available, but OctoPrint is there. # So keep trying to find a printer connected to it. if self._isAvailable: self._printing = False self._isAvailable = False self._doCallback() self._sleep(15) continue self._errorCount = 0 #We got a valid status, set the OctoPrint printer as available. self._isAvailable = True self._bedTemperature = None self._progress = response.body["progress"]["completion"] if self._progress == 0: self._progress = None if response.body['state'] == "Printing": self._printing = True self._jobFileName = response.body["job"]["file"]["name"] else: self._printing = False self._jobFileName = None response = self._httpClient.request('GET', '/api/printer/tool') if response.isOk(): self._hotendTemperature[0] = response.body['tool0']['actual'] self._hotendTemperature[1] = response.body['tool1']['actual'] self._hotendTemperature[2] = response.body['tool2']['actual'] response = self._httpClient.request('GET', '/api/printer/bed') if response.isOk(): self._bedTemperature = response.body['bed']['actual'] self._doCallback() if self._printing: self._sleep(1) else: self._sleep(5) def _octoprintGetApiKeyThread(self): while True: if self._needsAuthorization: pass self._sleep(5) def _sleep(self, timeOut): while timeOut > 0.0: if not self._interruptSleep: time.sleep(0.1) timeOut -= 0.1 self._interruptSleep = False
def _octoprintThread(self): self._waitDelay = 0 while True: updated = self._config.updateConfigFromFile() if updated: for printer in self._config.getPrinters(): connection = self._connectionMap[printer.getKey()] if not connection: self._addPrinter(printer) else: connection.setApiKey(printer.getApiKey()) if self._config.getDiscovery(): for ssdpResponse in discover("ssdp:all"): try: if ssdpResponse.usn not in self._ignored and ssdpResponse.usn not in self._connectionMap.keys( ): scheme, host, port, path = self._parseLocation( ssdpResponse.location) httpResponse = OctoPrintHttpClient( scheme, host, port, "", "xml").request("GET", path) if not httpResponse.isOk( ) or httpResponse.body is None: self._ignored.append(ssdpResponse.usn) continue manufacturer = httpResponse.body.find( "{urn:schemas-upnp-org:device-1-0}device/{urn:schemas-upnp-org:device-1-0}manufacturer" ) if manufacturer is not None: manufacturer = manufacturer.text presentationURL = httpResponse.body.find( "{urn:schemas-upnp-org:device-1-0}device/{urn:schemas-upnp-org:device-1-0}presentationURL" ) if presentationURL is not None: presentationURL = presentationURL.text friendlyName = httpResponse.body.find( "{urn:schemas-upnp-org:device-1-0}device/{urn:schemas-upnp-org:device-1-0}friendlyName" ) if friendlyName is not None: friendlyName = friendlyName.text if manufacturer and presentationURL and "octoprint" in manufacturer.lower( ): scheme, host, port, path = self._parseLocation( presentationURL) printer = OctoPrintPrinter( friendlyName, scheme, host, port, path, None, ssdpResponse.usn) self._config.updatePrinter(printer) self._addPrinter(printer) else: self._ignored.append(ssdpResponse.usn) time.sleep(0.01) except: print "Response Error: ({}:{})".format( ssdpResponse.usn, ssdpResponse.location) traceback.print_exc() self._ignored.append(ssdpResponse.usn) # Delay a bit more after every request. This so we do not stress the ssdp services too much if self._waitDelay < 10: self._waitDelay += 1 time.sleep(self._waitDelay * 30)
class OctoPrintPrinterConnection(printerConnectionBase.printerConnectionBase): """ Class to connect and print files with the OctoPrint Auto-detects if the OctoPrint box is available and handles communication with the OctoPrint API """ def __init__(self, key, name, scheme, host, port, path, apiKey, group): super(OctoPrintPrinterConnection, self).__init__(name) print "{} Connection created: {}://{}:{}{}".format( name, scheme, host, port, path) self._group = group self._key = key self._httpClient = OctoPrintHttpClient(scheme, host, port, path, "json") if apiKey: self.setApiKey(apiKey) self._isAvailable = False self._printing = False self._jobFileName = None self._progress = 0.0 self._printFilename = None self._hotendTemperature = [None] * 4 self._bedTemperature = None self._needsAuthorization = False self._errorCount = 0 self._interruptSleep = False self.checkThread = threading.Thread(target=self._octoprintThread) self.checkThread.daemon = True self.checkThread.start() self.getApiKeyThread = threading.Thread( target=self._octoprintGetApiKeyThread) self.getApiKeyThread.daemon = True self.getApiKeyThread.start() def setApiKey(self, apiKey): self._httpClient.addHeader("X-Api-Key", apiKey) #Load the file into memory for printing. def loadGCodeDataForFilename(self, dataStream, filename): if self._printing: return False self._printFilename = filename response = self._httpClient.request("POST", "/api/files/local", dataStream, filename) if response.isOk(): self._printFilename = filename self._doCallback() if response.isOk(): return True else: return False #Start printing the previously loaded file def startPrint(self): if self._printing or not self._printFilename: return response = self._httpClient.request( "POST", "/api/files/local/{}".format(self._printFilename), { "command": "select", "print": True }) if response.isOk(): self._printing = True self._interruptSleep = True else: self._printing = False self._progress = 0.0 self._printFilename = None #Abort the previously loaded print file def cancelPrint(self): if not self._printing: return response = self._httpClient.request('POST', '/api/job', {'command': 'cancel'}) if response.isOk(): self._printing = False def isPrinting(self): return self._printing #Amount of progression of the current print file. 0.0 to 1.0 def getPrintProgress(self): return self._progress or 0.0 # Return if the printer with this connection type is available def isAvailable(self): return self._isAvailable #Are we able to send a direct coammand with sendCommand at this moment in time. def isAbleToSendDirectCommand(self): #The send command appears to be in flux, so not going to support for now return False #Directly send a command to the printer. def sendCommand(self, command): return # Get the connection status string. This is displayed to the user and can be used to communicate # various information to the user. def getStatusString(self): if not self._isAvailable: return "OctoPrint is not found, or does not have a printer connected currently" elif self._printing: return "Currently printing {}".format(self._jobFileName) else: return "OctoPrint is ready to print" #Get the temperature of an extruder, returns None is no temperature is known for this extruder def getTemperature(self, extruder): return self._hotendTemperature[extruder] #Get the temperature of the heated bed, returns None is no temperature is known for the heated bed def getBedTemperature(self): return self._bedTemperature def _octoprintThread(self): while True: response = self._httpClient.request('GET', '/api/job') if response.isUnauthorized(): self._needsAuthorization = True self._sleep(60) continue if not response.isOk(): # No API, wait 5 seconds before looking for OctoPrint again. # API gave back an error # OctoPrint could also be offline, if we reach a high enough errorCount then assume it is gone. self._errorCount += 1 if self._errorCount > 10: if self._isAvailable: self._printing = False self._isAvailable = False self._doCallback() self._sleep(15) self._group.remove(self._key) return else: self._sleep(3) continue if response.body['state'] == 'Closed' or response.body[ 'state'] == "Connecting": # No printer connected, we do not have a printer available, but OctoPrint is there. # So keep trying to find a printer connected to it. if self._isAvailable: self._printing = False self._isAvailable = False self._doCallback() self._sleep(15) continue self._errorCount = 0 #We got a valid status, set the OctoPrint printer as available. self._isAvailable = True self._bedTemperature = None self._progress = response.body["progress"]["completion"] if self._progress == 0: self._progress = None if response.body['state'] == "Printing": self._printing = True self._jobFileName = response.body["job"]["file"]["name"] else: self._printing = False self._jobFileName = None response = self._httpClient.request('GET', '/api/printer/tool') if response.isOk(): self._hotendTemperature[0] = response.body['tool0']['actual'] self._hotendTemperature[1] = response.body['tool1']['actual'] self._hotendTemperature[2] = response.body['tool2']['actual'] response = self._httpClient.request('GET', '/api/printer/bed') if response.isOk(): self._bedTemperature = response.body['bed']['actual'] self._doCallback() if self._printing: self._sleep(1) else: self._sleep(5) def _octoprintGetApiKeyThread(self): while True: if self._needsAuthorization: pass self._sleep(5) def _sleep(self, timeOut): while timeOut > 0.0: if not self._interruptSleep: time.sleep(0.1) timeOut -= 0.1 self._interruptSleep = False