import math
import numpy
import os
-import warnings
import threading
import traceback
import platform
-import sys
import urllib
import urllib2
import hashlib
import socket
import struct
import errno
-import cStringIO as StringIO
+import inspect
+from Cura.util.bigDataStorage import BigDataStorage
from Cura.util import profile
from Cura.util import pluginInfo
from Cura.util import version
Finds and returns the path to the current engine executable. This is OS depended.
:return: The full path to the engine executable.
"""
+ base_search_path = os.path.dirname(inspect.getfile(getEngineFilename))
+ search_filename = 'CuraEngine'
if platform.system() == 'Windows':
+ search_filename += '.exe'
if version.isDevVersion() and os.path.exists('C:/Software/Cura_SteamEngine/_bin/Release/Cura_SteamEngine.exe'):
return 'C:/Software/Cura_SteamEngine/_bin/Release/Cura_SteamEngine.exe'
- return os.path.abspath(os.path.join(os.path.dirname(__file__), '../..', 'CuraEngine.exe'))
- if hasattr(sys, 'frozen'):
- return os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../../..', 'CuraEngine'))
+ for n in xrange(0, 10):
+ full_filename = os.path.abspath(os.path.join(base_search_path, '/'.join(['..'] * n), search_filename))
+ if os.path.isfile(full_filename):
+ return full_filename
+ full_filename = os.path.abspath(os.path.join(base_search_path, '/'.join(['..'] * n), 'CuraEngine', search_filename))
+ if os.path.isfile(full_filename):
+ return full_filename
if os.path.isfile('/usr/bin/CuraEngine'):
return '/usr/bin/CuraEngine'
if os.path.isfile('/usr/local/bin/CuraEngine'):
return '/usr/local/bin/CuraEngine'
- tempPath = os.path.abspath(os.path.join(os.path.dirname(__file__), '../..', 'CuraEngine'))
- if os.path.isdir(tempPath):
- tempPath = os.path.join(tempPath,'CuraEngine')
- return tempPath
+ return ''
class EngineResult(object):
"""
"""
def __init__(self):
self._engineLog = []
- self._gcodeData = StringIO.StringIO()
+ self._gcodeData = BigDataStorage()
self._polygons = []
self._replaceInfo = {}
self._success = False
if self._printTimeSeconds is None:
return ''
if int(self._printTimeSeconds / 60 / 60) < 1:
- return '%d minutes' % (int(self._printTimeSeconds / 60) % 60)
+ return _('%d minutes') % (int(self._printTimeSeconds / 60) % 60)
if int(self._printTimeSeconds / 60 / 60) == 1:
- return '%d hour %d minutes' % (int(self._printTimeSeconds / 60 / 60), int(self._printTimeSeconds / 60) % 60)
- return '%d hours %d minutes' % (int(self._printTimeSeconds / 60 / 60), int(self._printTimeSeconds / 60) % 60)
+ return _('%d hour %d minutes') % (int(self._printTimeSeconds / 60 / 60), int(self._printTimeSeconds / 60) % 60)
+ return _('%d hours %d minutes') % (int(self._printTimeSeconds / 60 / 60), int(self._printTimeSeconds / 60) % 60)
def getFilamentAmount(self, e=0):
if self._filamentMM[e] == 0.0:
return None
- return '%0.2f meter %0.0f gram' % (float(self._filamentMM[e]) / 1000.0, self.getFilamentWeight(e) * 1000.0)
+ return _('%0.2f meter %0.0f gram') % (float(self._filamentMM[e]) / 1000.0, self.getFilamentWeight(e) * 1000.0)
def getLog(self):
return self._engineLog
def getGCode(self):
- data = self._gcodeData.getvalue()
- if len(self._replaceInfo) > 0:
- block0 = data[0:2048]
- for k, v in self._replaceInfo.items():
- v = (v + ' ' * len(k))[:len(k)]
- block0 = block0.replace(k, v)
- return block0 + data[2048:]
- return data
+ self._gcodeData.seekStart()
+ return self._gcodeData
def setGCode(self, gcode):
- self._gcodeData = StringIO.StringIO(gcode)
+ self._gcodeData = BigDataStorage()
+ self._gcodeData.write(gcode)
self._replaceInfo = {}
def addLog(self, line):
self._modelHash = hash
def setFinished(self, result):
+ if result:
+ for k, v in self._replaceInfo.items():
+ self._gcodeData.replaceAtStart(k, v)
self._finished = result
def isFinished(self):
return None
if self._gcodeInterpreter.layerList is None and self._gcodeLoadThread is None:
self._gcodeInterpreter.progressCallback = self._gcodeInterpreterCallback
- self._gcodeLoadThread = threading.Thread(target=lambda : self._gcodeInterpreter.load(self._gcodeData))
+ self._gcodeLoadThread = threading.Thread(target=lambda : self._gcodeInterpreter.load(self._gcodeData.clone()))
self._gcodeLoadCallback = loadCallback
self._gcodeLoadThread.daemon = True
self._gcodeLoadThread.start()
time.sleep(0.1)
return self._gcodeLoadCallback(self, progress)
- def submitInfoOnline(self):
+ '''def submitInfoOnline(self):
if profile.getPreference('submit_slice_information') != 'True':
return
if version.isDevVersion():
'preferences': self._preferencesString,
'modelhash': self._modelHash,
'version': version.getVersion(),
+ 'printtime': self._printTimeSeconds,
+ 'filament': ','.join(map(str, self._filamentMM)),
}
try:
- f = urllib2.urlopen("https://www.youmagine.com/curastats/", data = urllib.urlencode(data), timeout = 1)
+ f = urllib2.urlopen("https://stats.youmagine.com/curastats/slice", data = urllib.urlencode(data), timeout = 1)
f.read()
f.close()
except:
import traceback
- traceback.print_exc()
+ traceback.print_exc()'''
class Engine(object):
"""
self._objCount = 0
self._result = None
+ self._engine_executable = getEngineFilename()
self._serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._serverPortNr = 0xC20A
- while True:
+ for potential_port in xrange(0xC20A, 0xFFFF):
+ self._serverPortNr = potential_port
try:
self._serversocket.bind(('127.0.0.1', self._serverPortNr))
- except:
- print "Failed to listen on port: %d" % (self._serverPortNr)
- self._serverPortNr += 1
- if self._serverPortNr > 0xFFFF:
- print "Failed to listen on any port..."
- break
- else:
break
+ except:
+ print("Failed to listen on port: %d" % (self._serverPortNr))
+ else:
+ print("Failed to listen on any port, this is a fatal error")
+ exit(10)
thread = threading.Thread(target=self._socketListenThread)
thread.daemon = True
thread.start()
def cleanup(self):
self.abortEngine()
+ self.wait()
self._serversocket.close()
def abortEngine(self):
self._process.terminate()
except:
pass
- if self._thread is not None:
- self._thread.join()
- self._thread = None
def wait(self):
if self._thread is not None:
def runEngine(self, scene):
if len(scene.objects()) < 1:
return
+ self._thread = threading.Thread(target=self._runEngine, args=(scene, self._thread, pluginInfo.getPostProcessPluginConfig()))
+ self._thread.daemon = True
+ self._thread.start()
+
+ def _runEngine(self, scene, old_thread, pluginConfig):
+ if old_thread is not None:
+ if self._process is not None:
+ self._process.terminate()
+ old_thread.join()
+ self._callback(-1.0)
+
extruderCount = 1
for obj in scene.objects():
if scene.checkPlatform(obj):
extruderCount = max(extruderCount, profile.minimalExtruderCount())
- commandList = [getEngineFilename(), '-v', '-p']
+ commandList = [self._engine_executable, '-v', '-p']
for k, v in self._engineSettings(extruderCount).iteritems():
commandList += ['-s', '%s=%s' % (k, str(v))]
commandList += ['-g', '%d' % (self._serverPortNr)]
commandList += ['$' * len(obj._meshList)]
self._objCount += 1
modelHash = hash.hexdigest()
- if self._objCount > 0:
- self._thread = threading.Thread(target=self._watchProcess, args=(commandList, self._thread, engineModelData, modelHash))
- self._thread.daemon = True
- self._thread.start()
+ if self._objCount < 1:
+ return
+ if self._thread != threading.currentThread():
+ return
- def _watchProcess(self, commandList, oldThread, engineModelData, modelHash):
- if oldThread is not None:
- if self._process is not None:
- self._process.terminate()
- oldThread.join()
- self._callback(-1.0)
self._modelData = engineModelData
try:
self._process = self._runEngineProcess(commandList)
except OSError:
traceback.print_exc()
return
- if self._thread != threading.currentThread():
- self._process.terminate()
self._result = EngineResult()
self._result.addLog('Running: %s' % (' '.join(commandList)))
logThread.daemon = True
logThread.start()
- data = self._process.stdout.read(4096)
- while len(data) > 0:
- self._result._gcodeData.write(data)
+ try:
data = self._process.stdout.read(4096)
-
- returnCode = self._process.wait()
- logThread.join()
- if returnCode == 0:
- pluginError = pluginInfo.runPostProcessingPlugins(self._result)
- if pluginError is not None:
- print pluginError
- self._result.addLog(pluginError)
- self._result.setFinished(True)
- self._callback(1.0)
- else:
- for line in self._result.getLog():
- print line
+ while len(data) > 0:
+ if self._thread != threading.currentThread():
+ self._process.terminate()
+ self._result._gcodeData.write(data)
+ data = self._process.stdout.read(4096)
+
+ returnCode = self._process.wait()
+ logThread.join()
+ self._result.addLog("Slicer process returned : %d" % returnCode)
+ if returnCode == 0:
+ plugin_error = pluginInfo.runPostProcessingPlugins(self._result, pluginConfig)
+ if plugin_error is not None:
+ self._result.addLog(plugin_error)
+ self._result.setFinished(True)
+ self._callback(1.0)
+ else:
+ self._callback(-1.0)
+ self._process = None
+ except MemoryError:
+ self._result.addLog("MemoryError")
self._callback(-1.0)
- self._process = None
+ finally:
+ try:
+ with open(os.path.join(profile.getBasePath(), 'engine.log'), "w") as f:
+ for line in self._result.getLog():
+ f.write(line + "\n")
+ except:
+ pass
def _watchStderr(self, stderr):
objectNr = 0
'extruderOffset[2].Y': int(profile.getMachineSettingFloat('extruder_offset_y2') * 1000),
'extruderOffset[3].X': int(profile.getMachineSettingFloat('extruder_offset_x3') * 1000),
'extruderOffset[3].Y': int(profile.getMachineSettingFloat('extruder_offset_y3') * 1000),
+ 'zOffset': int(profile.getMachineSettingFloat('extruder_z_offset') * 1000),
'fixHorrible': 0,
}
fanFullHeight = int(profile.getProfileSettingFloat('fan_full_height') * 1000)
settings['raftInterfaceThickness'] = int(profile.getProfileSettingFloat('raft_interface_thickness') * 1000)
settings['raftInterfaceLinewidth'] = int(profile.getProfileSettingFloat('raft_interface_linewidth') * 1000)
settings['raftInterfaceLineSpacing'] = int(profile.getProfileSettingFloat('raft_interface_linewidth') * 1000 * 2.0)
- settings['raftAirGapLayer0'] = int(profile.getProfileSettingFloat('raft_airgap') * 1000)
+ settings['raftAirGapLayer0'] = int(profile.getProfileSettingFloat('raft_airgap') * 1000 + profile.getProfileSettingFloat('raft_airgap_all') * 1000)
+ settings['raftAirGap'] = int(profile.getProfileSettingFloat('raft_airgap_all') * 1000)
settings['raftBaseSpeed'] = int(profile.getProfileSettingFloat('bottom_layer_speed'))
- settings['raftFanSpeed'] = 100
- settings['raftSurfaceThickness'] = settings['raftInterfaceThickness']
- settings['raftSurfaceLinewidth'] = int(profile.calculateEdgeWidth() * 1000)
- settings['raftSurfaceLineSpacing'] = int(profile.calculateEdgeWidth() * 1000 * 0.9)
+ settings['raftFanSpeed'] = 0
+ settings['raftSurfaceThickness'] = int(profile.getProfileSettingFloat('raft_surface_thickness') * 1000)
+ settings['raftSurfaceLinewidth'] = int(profile.getProfileSettingFloat('raft_surface_linewidth') * 1000)
+ settings['raftSurfaceLineSpacing'] = int(profile.getProfileSettingFloat('raft_surface_linewidth') * 1000)
settings['raftSurfaceLayers'] = int(profile.getProfileSettingFloat('raft_surface_layers'))
settings['raftSurfaceSpeed'] = int(profile.getProfileSettingFloat('bottom_layer_speed'))
else: