chiark / gitweb /
Added class for Doodle3D printing.
authordaid <daid303@gmail.com>
Fri, 22 Nov 2013 13:44:39 +0000 (14:44 +0100)
committerdaid <daid303@gmail.com>
Fri, 22 Nov 2013 13:44:39 +0000 (14:44 +0100)
Cura/util/doodle3dConnect.py [new file with mode: 0644]

diff --git a/Cura/util/doodle3dConnect.py b/Cura/util/doodle3dConnect.py
new file mode 100644 (file)
index 0000000..5ba3fad
--- /dev/null
@@ -0,0 +1,160 @@
+__copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
+
+import threading
+import json
+import httplib as httpclient
+import urllib
+import time
+
+#Class to connect and print files with the doodle3d.com wifi box
+# Auto-detects if the Doodle3D box is available with a printer
+class doodle3dConnect(object):
+       def __init__(self):
+               self._http = None
+               self._connected = False
+               self._printing = False
+               self._fileBlocks = []
+               self._blockIndex = None
+               self._lineCount = 0
+               self._progressLine = 0
+               self._hotendTemperature = [0] * 4
+               self._bedTemperature = 0
+
+               self.checkThread = threading.Thread(target=self._checkForDoodle3D)
+               self.checkThread.daemon = True
+               self.checkThread.start()
+
+       def loadFile(self, filename):
+               if self._printing:
+                       return
+               self._fileBlocks = []
+               self._lineCount = 0
+               block = []
+               blockSize = 0
+               f = open(filename, "r")
+               for line in f:
+                       if ';' in line:
+                               line = line[:line.index(';')]
+                       line = line.strip()
+
+                       if len(line) < 1:
+                               continue
+                       self._lineCount += 1
+                       if blockSize + len(line) > 2048:
+                               self._fileBlocks.append('\n'.join(block) + '\n')
+                               block = []
+                               blockSize = 0
+                       blockSize += len(line) + 1
+                       block.append(line)
+               self._fileBlocks.append('\n'.join(block) + '\n')
+               f.close()
+
+       def startPrint(self):
+               if self._printing:
+                       return
+               self._progressLine = 0
+               self._blockIndex = 0
+               self._printing = True
+
+       def stopPrint(self):
+               if not self._printing:
+                       return
+               if self._request('POST', '/d3dapi/printer/stop', {'gcode': 'M104 S0\nG28'}):
+                       self._printing = False
+
+       def isConnected(self):
+               return self._connected
+
+       def isPrinting(self):
+               return self._printing
+
+       def _checkForDoodle3D(self):
+               while True:
+                       stateReply = self._request('GET', '/d3dapi/printer/state')
+                       if stateReply is None:  #No API, wait 15 seconds before looking for Doodle3D again.
+                               self._connected = False
+                               time.sleep(15)
+                               continue
+                       if not stateReply:              #API gave back an error (this can happen if the Doodle3D box is connecting to the printer)
+                               self._connected = False
+                               time.sleep(5)
+                               continue
+                       self._connected = True
+
+                       if stateReply['data']['state'] == 'idle':
+                               if self._printing:
+                                       if self._blockIndex < len(self._fileBlocks):
+                                               if self._request('POST', '/d3dapi/printer/print', {'gcode': self._fileBlocks[self._blockIndex], 'start': 'True', 'first': 'True'}):
+                                                       self._blockIndex += 1
+                                       else:
+                                               self._printing = False
+                       if stateReply['data']['state'] == 'printing':
+                               if self._printing:
+                                       if self._blockIndex < len(self._fileBlocks):
+                                               for n in xrange(0, 5):
+                                                       if self._blockIndex < len(self._fileBlocks):
+                                                               if self._request('POST', '/d3dapi/printer/print', {'gcode': self._fileBlocks[self._blockIndex]}):
+                                                                       self._blockIndex += 1
+                                       else:
+                                               #If we are no longer sending new GCode delay a bit so we request the status less often.
+                                               time.sleep(1)
+                                       progress = self._request('GET', '/d3dapi/printer/progress')
+                                       if progress:
+                                               self._progressLine = progress['data']['current_line']
+                                       temperature = self._request('GET', '/d3dapi/printer/temperature')
+                                       if temperature:
+                                               self._hotendTemperature[0] = temperature['data']['hotend']
+                                               self._bedTemperature = temperature['data']['bed']
+                               else:
+                                       #Got a printing state without us having send the print file, set the state to printing, but make sure we never send anything.
+                                       progress = self._request('GET', '/d3dapi/printer/progress')
+                                       if progress:
+                                               self._printing = True
+                                               self._blockIndex = len(self._fileBlocks)
+                                               self._lineCount = progress['data']['total_lines']
+
+       def _request(self, method, path, postData = None):
+               if self._http is None:
+                       self._http = httpclient.HTTPConnection('draw.doodle3d.com')
+               try:
+                       if postData is not None:
+                               self._http.request(method, path, urllib.urlencode(postData), {"Content-type": "application/x-www-form-urlencoded"})
+                       else:
+                               self._http.request(method, path, headers={"Content-type": "application/x-www-form-urlencoded"})
+               except:
+                       self._http.close()
+                       return None
+               try:
+                       response = self._http.getresponse()
+                       responseText = response.read()
+               except:
+                       self._http.close()
+                       return None
+               try:
+                       response = json.loads(responseText)
+               except ValueError:
+                       self._http.close()
+                       return None
+               if response['status'] != 'success':
+                       return False
+
+               return response
+
+if __name__ == '__main__':
+       d = doodle3dConnect()
+       print 'Searching for Doodle3D box'
+       while not d.isConnected():
+               time.sleep(1)
+
+       while d.isPrinting():
+               print 'Doodle3D already printing! Requesting stop!'
+               d.stopPrint()
+               time.sleep(5)
+
+       print 'Doodle3D box found, printing!'
+       d.loadFile("C:/Models/belt-tensioner-wave_export.gcode")
+       d.startPrint()
+       while d.isPrinting() and d.isConnected():
+               time.sleep(1)
+               print d._progressLine, d._lineCount, d._blockIndex, len(d._fileBlocks)
+       print 'Done'