def __init__(self): self.smoothie_com = SmoothieCom(Config.SMOOTHIE_URL, Config.SMOOTHIE_PORT) self.COMMAND_TYPE_TO_HANDLER = { 'move': self.move, 'position': self.position, 'hardstop': self.hardstop, 'home': self.home, 'acceleration': self.acceleration, 'speed': self.speed }
class CommandToGCode(object): """ this module converts front-end commands to GCode then sends GCode strings to Smoothie-Com module """ def __init__(self): self.smoothie_com = SmoothieCom(Config.SMOOTHIE_URL, Config.SMOOTHIE_PORT) self.COMMAND_TYPE_TO_HANDLER = { 'move': self.move, 'position': self.position, 'hardstop': self.hardstop, 'home': self.home, 'acceleration': self.acceleration, 'speed': self.speed } @asyncio.coroutine def connect(self): """ tell the smoothie module to connect to the motor controller return True if successful """ return (yield from self.smoothie_com.connect()) @asyncio.coroutine def send_gcode(self, gcode : str): """ send a GCode string to the smoothie module """ if gcode: return (yield from self.smoothie_com.send(gcode)) @asyncio.coroutine def process(self, command): """ receive front-end commands, and convert them to GCode returns None or a coordinate dict """ command_type = command.get('type', '') command_data = command.get('data', {}) gcode_list = None try: handler = self.COMMAND_TYPE_TO_HANDLER[command_type] gcode_list = handler(command_data) except KeyError: logger.error('invalid command: {}'.format(command_type)) if gcode_list: coords = None # pass the data to the matching method, returning an array of gcode strings for gcode_string in gcode_list: ret = yield from self.send_gcode(gcode_string) if ret != None: coords = self.parse_coordinates(ret) return coords def parse_coordinates(self, coords): """ removes unnecessary data from the coordinates object returned from smoothie-com returns a dict """ if isinstance(coords, dict): new_coords = {} for axis, label in Config.GCODE_KEYS['position'].items(): if coords.get(label, None) != None: new_coords[axis] = coords[label] return new_coords def create_gcode_string(self, data, type): """ turns a front-end command dict into the equivalent gcode string returns a string """ temp_string = '' for axis in Config.GCODE_AXIS.get(type, []): if data.get(axis, None): temp_key = Config.GCODE_KEYS[type][axis] temp_string += ' {0}{1}'.format( temp_key , data[axis] ) # only return the string if it has grown beyond the initial command if len(temp_string): return Config.GCODE_COMMANDS[type] + temp_string # prepend with the appropriate gcode command else: return '' def move(self, data): """ create absolute or relative movement gcode returns array of strings """ mode = Config.GCODE_COMMANDS['move_rel'] if data.get('relative', False) else Config.GCODE_COMMANDS['move_abs'] return [ mode , self.create_gcode_string(data, 'move') ] def position(self, data): """ GET or SET the current axis positions returns array of strings """ if data and isinstance(data, dict) and len(data.keys()): return [ self.create_gcode_string(data, 'position') ] else: return [ Config.GCODE_COMMANDS['position_get'] ] def speed(self, data): """ create 'speed' gcode returns array of strings """ return [ self.create_gcode_string(data, 'speed') ] def acceleration(self, data): """ create 'acceleration' gcode returns array of strings """ return [ self.create_gcode_string(data, 'acceleration') ] def home(self, data): """ create 'home' gcode: if no axis are specified, all axis are homed at once returns array of strings """ temp_string = Config.GCODE_COMMANDS['home'] for n in (data if data else []): # a None might be passed temp_string += ' {}'.format(str(n[0]).upper()) # UPPER CASE return [ temp_string ] def hardstop(self, data): """ create 'hardstop' gcode: halt the motor driver, then reset it returns array of strings """ return [ Config.GCODE_COMMANDS['hardstop'] , Config.GCODE_COMMANDS['reset'] ]