1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
5 import httplib as httpclient
9 from Cura.util.printerConnection import printerConnectionBase
11 #Class to connect and print files with the doodle3d.com wifi box
12 # Auto-detects if the Doodle3D box is available with a printer
13 class doodle3dConnect(printerConnectionBase.printerConnectionBase):
15 super(doodle3dConnect, self).__init__()
18 self._isAvailable = False
19 self._printing = False
21 self._blockIndex = None
23 self._progressLine = 0
24 self._hotendTemperature = [0] * 4
25 self._bedTemperature = 0
27 self.checkThread = threading.Thread(target=self._doodle3Dthread)
28 self.checkThread.daemon = True
29 self.checkThread.start()
31 #Load the file into memory for printing.
32 def loadFile(self, filename):
39 f = open(filename, "r")
41 #Strip out comments, we do not need to send comments
43 line = line[:line.index(';')]
44 #Strip out whitespace at the beginning/end this saves data to send.
50 #Put the lines in 2k sized blocks, so we can send those blocks as http requests.
51 if blockSize + len(line) > 2048:
52 self._fileBlocks.append('\n'.join(block) + '\n')
55 blockSize += len(line) + 1
57 self._fileBlocks.append('\n'.join(block) + '\n')
60 #Start printing the previously loaded file
62 if self._printing or len(self._fileBlocks) < 1:
64 self._progressLine = 0
68 #Abort the previously loaded print file
69 def cancelPrint(self):
70 if not self._printing:
72 if self._request('POST', '/d3dapi/printer/stop', {'gcode': 'M104 S0\nG28'}):
73 self._printing = False
78 #Amount of progression of the current print file. 0.0 to 1.0
79 def printProgress(self):
80 if self._lineCount < 1:
82 return float(d._progressLine) / float(d._lineCount)
84 # Return if the printer with this connection type is available
85 def isAvailable(self):
86 return self._isAvailable
88 # Get the connection status string. This is displayed to the user and can be used to communicate
89 # various information to the user.
90 def getStatusString(self):
93 def _doodle3Dthread(self):
95 stateReply = self._request('GET', '/d3dapi/printer/state')
96 if stateReply is None: #No API, wait 15 seconds before looking for Doodle3D again.
97 self._isAvailable = False
100 if not stateReply: #API gave back an error (this can happen if the Doodle3D box is connecting to the printer)
101 self._isAvailable = False
104 self._isAvailable = True
106 if stateReply['data']['state'] == 'idle':
108 if self._blockIndex < len(self._fileBlocks):
109 if self._request('POST', '/d3dapi/printer/print', {'gcode': self._fileBlocks[self._blockIndex], 'start': 'True', 'first': 'True'}):
110 self._blockIndex += 1
112 self._printing = False
113 if stateReply['data']['state'] == 'printing':
115 if self._blockIndex < len(self._fileBlocks):
116 for n in xrange(0, 5):
117 if self._blockIndex < len(self._fileBlocks):
118 if self._request('POST', '/d3dapi/printer/print', {'gcode': self._fileBlocks[self._blockIndex]}):
119 self._blockIndex += 1
121 #If we are no longer sending new GCode delay a bit so we request the status less often.
123 progress = self._request('GET', '/d3dapi/printer/progress')
125 self._progressLine = progress['data']['current_line']
126 temperature = self._request('GET', '/d3dapi/printer/temperature')
128 self._hotendTemperature[0] = temperature['data']['hotend']
129 self._bedTemperature = temperature['data']['bed']
131 #Got a printing state without us having send the print file, set the state to printing, but make sure we never send anything.
132 progress = self._request('GET', '/d3dapi/printer/progress')
134 self._printing = True
135 self._blockIndex = len(self._fileBlocks)
136 self._lineCount = progress['data']['total_lines']
138 def _request(self, method, path, postData = None):
139 if self._http is None:
140 self._http = httpclient.HTTPConnection('draw.doodle3d.com')
142 if postData is not None:
143 self._http.request(method, path, urllib.urlencode(postData), {"Content-type": "application/x-www-form-urlencoded"})
145 self._http.request(method, path, headers={"Content-type": "application/x-www-form-urlencoded"})
150 response = self._http.getresponse()
151 responseText = response.read()
156 response = json.loads(responseText)
160 if response['status'] != 'success':
165 if __name__ == '__main__':
166 d = doodle3dConnect()
167 print 'Searching for Doodle3D box'
168 while not d.isAvailable():
171 while d.isPrinting():
172 print 'Doodle3D already printing! Requesting stop!'
176 print 'Doodle3D box found, printing!'
177 d.loadFile("C:/Models/belt-tensioner-wave_export.gcode")
179 while d.isPrinting() and d.isAvailable():
181 print d._progressLine, d._lineCount, d._blockIndex, len(d._fileBlocks)