diff --git a/klippy/clocksync.py b/klippy/clocksync.py index 65c3face..b31908b6 100644 --- a/klippy/clocksync.py +++ b/klippy/clocksync.py @@ -29,20 +29,19 @@ class ClockSync: self.last_prediction_time = 0. def connect(self, serial): self.serial = serial - msgparser = serial.msgparser - self.mcu_freq = msgparser.get_constant_float('CLOCK_FREQ') + self.mcu_freq = serial.msgparser.get_constant_float('CLOCK_FREQ') # Load initial clock and frequency - uptime_msg = msgparser.create_command('get_uptime') - params = serial.send_with_response(uptime_msg, 'uptime') + get_uptime_cmd = serial.lookup_command('get_uptime') + params = get_uptime_cmd.send_with_response(response='uptime') self.last_clock = (params['high'] << 32) | params['clock'] self.clock_avg = self.last_clock self.time_avg = params['#sent_time'] self.clock_est = (self.time_avg, self.clock_avg, self.mcu_freq) self.prediction_variance = (.001 * self.mcu_freq)**2 # Enable periodic get_status timer - self.status_cmd = msgparser.create_command('get_status') + self.status_cmd = serial.lookup_command('get_status') for i in range(8): - params = serial.send_with_response(self.status_cmd, 'status') + params = self.status_cmd.send_with_response(response='status') self._handle_status(params) self.reactor.pause(0.100) serial.register_callback(self._handle_status, 'status') @@ -57,7 +56,7 @@ class ClockSync: serial.set_clock_est(freq, self.reactor.monotonic(), 0) # MCU clock querying (status callback invoked from background thread) def _status_event(self, eventtime): - self.serial.send(self.status_cmd) + self.status_cmd.send() return eventtime + 1.0 def _handle_status(self, params): # Extend clock to 64bit diff --git a/klippy/console.py b/klippy/console.py index cd7facfd..0259864f 100755 --- a/klippy/console.py +++ b/klippy/console.py @@ -86,11 +86,10 @@ class KeyboardReader: self.output("Error: %s" % (str(e),)) return try: - msg = self.ser.msgparser.create_command(' '.join(parts[2:])) + self.ser.send(' '.join(parts[2:]), minclock=val) except msgproto.error as e: self.output("Error: %s" % (str(e),)) return - self.ser.send(msg, minclock=val) def command_FLOOD(self, parts): try: count = int(parts[1]) @@ -98,18 +97,18 @@ class KeyboardReader: except ValueError as e: self.output("Error: %s" % (str(e),)) return - try: - msg = self.ser.msgparser.create_command(' '.join(parts[3:])) - except msgproto.error as e: - self.output("Error: %s" % (str(e),)) - return + msg = ' '.join(parts[3:]) delay_clock = int(delay * self.mcu_freq) msg_clock = int(self.clocksync.get_clock(self.reactor.monotonic()) + self.mcu_freq * .200) - for i in range(count): - next_clock = msg_clock + delay_clock - self.ser.send(msg, minclock=msg_clock, reqclock=next_clock) - msg_clock = next_clock + try: + for i in range(count): + next_clock = msg_clock + delay_clock + self.ser.send(msg, minclock=msg_clock, reqclock=next_clock) + msg_clock = next_clock + except msgproto.error as e: + self.output("Error: %s" % (str(e),)) + return def command_SUPPRESS(self, parts): oid = None try: @@ -164,12 +163,7 @@ class KeyboardReader: if parts[0] in self.local_commands: self.local_commands[parts[0]](parts) return None - try: - msg = self.ser.msgparser.create_command(line) - except msgproto.error as e: - self.output("Error: %s" % (str(e),)) - return None - return msg + return line def process_kbd(self, eventtime): self.data += os.read(self.fd, 4096) @@ -184,7 +178,11 @@ class KeyboardReader: msg = self.translate(line.strip(), eventtime) if msg is None: continue - self.ser.send(msg) + try: + self.ser.send(msg) + except msgproto.error as e: + self.output("Error: %s" % (str(e),)) + return None self.data = kbdlines[-1] def main(): diff --git a/klippy/extras/replicape.py b/klippy/extras/replicape.py index aa1d14fd..320a5701 100644 --- a/klippy/extras/replicape.py +++ b/klippy/extras/replicape.py @@ -32,7 +32,6 @@ class pca9685_pwm: self._is_static = False self._last_clock = 0 self._pwm_max = 0. - self._cmd_queue = self._mcu.alloc_command_queue() self._set_cmd = None def get_mcu(self): return self._mcu @@ -73,17 +72,17 @@ class pca9685_pwm: self._start_value * self._pwm_max, self._shutdown_value * self._pwm_max, self._mcu.seconds_to_clock(self._max_duration))) + cmd_queue = self._mcu.alloc_command_queue() self._set_cmd = self._mcu.lookup_command( - "schedule_pca9685_out oid=%c clock=%u value=%hu") + "schedule_pca9685_out oid=%c clock=%u value=%hu", cq=cmd_queue) def set_pwm(self, print_time, value): clock = self._mcu.print_time_to_clock(print_time) if self._invert: value = 1. - value value = int(max(0., min(1., value)) * self._pwm_max + 0.5) self._replicape.note_pwm_enable(print_time, self._channel, value) - msg = self._set_cmd.encode(self._oid, clock, value) - self._mcu.send(msg, minclock=self._last_clock, reqclock=clock - , cq=self._cmd_queue) + self._set_cmd.send([self._oid, clock, value], + minclock=self._last_clock, reqclock=clock) self._last_clock = clock def set_digital(self, print_time, value): if value: @@ -137,6 +136,8 @@ class Replicape: "power_fan0": (pca9685_pwm, 7), "power_fan1": (pca9685_pwm, 8), "power_fan2": (pca9685_pwm, 9), "power_fan3": (pca9685_pwm, 10) } # Setup stepper config + self.send_spi_cmd = None + self.last_stepper_time = 0. self.stepper_dacs = {} shift_registers = [1, 0, 0, 1, 1] for port, name in enumerate('xyzeh'): @@ -159,9 +160,7 @@ class Replicape: self.stepper_dacs[channel] = cur / REPLICAPE_MAX_CURRENT self.pins[prefix + 'enable'] = (ReplicapeDACEnable, channel) self.enabled_channels = {ch: False for cl, ch in self.pins.values()} - self.disable_stepper_cmd = "send_spi bus=%d dev=%d msg=%s" % ( - REPLICAPE_SHIFT_REGISTER_BUS, REPLICAPE_SHIFT_REGISTER_DEVICE, - "".join(["%02x" % (x,) for x in reversed(shift_registers)])) + self.sr_disabled = tuple(reversed(shift_registers)) if [i for i in [0, 1, 2] if 11+i in self.stepper_dacs]: # Enable xyz steppers shift_registers[0] &= ~1 @@ -171,11 +170,15 @@ class Replicape: if (config.getboolean('standstill_power_down', False) and self.stepper_dacs): shift_registers[4] &= ~1 - self.enable_stepper_cmd = "send_spi bus=%d dev=%d msg=%s" % ( + self.sr_enabled = tuple(reversed(shift_registers)) + self.host_mcu.add_config_object(self) + self.host_mcu.add_config_cmd("send_spi bus=%d dev=%d msg=%s" % ( REPLICAPE_SHIFT_REGISTER_BUS, REPLICAPE_SHIFT_REGISTER_DEVICE, - "".join(["%02x" % (x,) for x in reversed(shift_registers)])) - self.host_mcu.add_config_cmd(self.disable_stepper_cmd) - self.last_stepper_time = 0. + "".join(["%02x" % (x,) for x in self.sr_disabled]))) + def build_config(self): + cmd_queue = self.host_mcu.alloc_command_queue() + self.send_spi_cmd = self.host_mcu.lookup_command( + "send_spi bus=%u dev=%u msg=%*s", cq=cmd_queue) def note_pwm_start_value(self, channel, start_value, shutdown_value): self.mcu_pwm_start_value |= not not start_value self.mcu_pwm_shutdown_value |= not not shutdown_value @@ -200,16 +203,17 @@ class Replicape: on_dacs = [1 for c in self.stepper_dacs.keys() if self.enabled_channels[c]] if not on_dacs: - cmd = self.disable_stepper_cmd + sr = self.sr_disabled elif is_enable and len(on_dacs) == 1: - cmd = self.enable_stepper_cmd + sr = self.sr_enabled else: return print_time = max(print_time, self.last_stepper_time + PIN_MIN_TIME) clock = self.host_mcu.print_time_to_clock(print_time) # XXX - the send_spi message should be scheduled - self.host_mcu.send(self.host_mcu.create_command(cmd), - minclock=clock, reqclock=clock) + self.send_spi_cmd.send([REPLICAPE_SHIFT_REGISTER_BUS, + REPLICAPE_SHIFT_REGISTER_DEVICE, sr], + minclock=clock, reqclock=clock) def setup_pin(self, pin_params): pin = pin_params['pin'] if pin not in self.pins: diff --git a/klippy/mcu.py b/klippy/mcu.py index fed45f82..c00db3c7 100644 --- a/klippy/mcu.py +++ b/klippy/mcu.py @@ -21,7 +21,7 @@ class MCU_stepper: self._commanded_pos = self._mcu_position_offset = 0. self._step_dist = self._inv_step_dist = 1. self._min_stop_interval = 0. - self._reset_cmd = self._get_position_cmd = None + self._reset_cmd_id = self._get_position_cmd = None self._ffi_lib = self._stepqueue = None def get_mcu(self): return self._mcu @@ -46,17 +46,17 @@ class MCU_stepper: self._invert_step)) self._mcu.add_config_cmd( "reset_step_clock oid=%d clock=0" % (self._oid,), is_init=True) - step_cmd = self._mcu.lookup_command( + step_cmd_id = self._mcu.lookup_command_id( "queue_step oid=%c interval=%u count=%hu add=%hi") - dir_cmd = self._mcu.lookup_command( + dir_cmd_id = self._mcu.lookup_command_id( "set_next_step_dir oid=%c dir=%c") - self._reset_cmd = self._mcu.lookup_command( + self._reset_cmd_id = self._mcu.lookup_command_id( "reset_step_clock oid=%c clock=%u") self._get_position_cmd = self._mcu.lookup_command( "stepper_get_position oid=%c") ffi_main, self._ffi_lib = chelper.get_ffi() self._stepqueue = ffi_main.gc(self._ffi_lib.stepcompress_alloc( - self._mcu.seconds_to_clock(max_error), step_cmd.msgid, dir_cmd.msgid, + self._mcu.seconds_to_clock(max_error), step_cmd_id, dir_cmd_id, self._invert_dir, self._oid), self._ffi_lib.stepcompress_free) self._mcu.register_stepqueue(self._stepqueue) @@ -87,15 +87,15 @@ class MCU_stepper: ret = self._ffi_lib.stepcompress_reset(self._stepqueue, 0) if ret: raise error("Internal error in stepcompress") - data = (self._reset_cmd.msgid, self._oid, 0) + data = (self._reset_cmd_id, self._oid, 0) ret = self._ffi_lib.stepcompress_queue_msg( self._stepqueue, data, len(data)) if ret: raise error("Internal error in stepcompress") if not did_trigger or self._mcu.is_fileoutput(): return - cmd = self._get_position_cmd.encode(self._oid) - params = self._mcu.send_with_response(cmd, 'stepper_position', self._oid) + params = self._get_position_cmd.send_with_response( + [self._oid], response='stepper_position', response_oid=self._oid) pos = params['pos'] if self._invert_dir: pos = -pos @@ -137,7 +137,6 @@ class MCU_endstop: self._pin = pin_params['pin'] self._pullup = pin_params['pullup'] self._invert = pin_params['invert'] - self._cmd_queue = mcu.alloc_command_queue() self._oid = self._home_cmd = self._query_cmd = None self._homing = False self._min_query_time = self._next_query_time = 0. @@ -162,10 +161,12 @@ class MCU_endstop: self._mcu.add_config_cmd( "end_stop_set_stepper oid=%d pos=%d stepper_oid=%d" % ( self._oid, i, s.get_oid()), is_init=True) + cmd_queue = self._mcu.alloc_command_queue() self._home_cmd = self._mcu.lookup_command( "end_stop_home oid=%c clock=%u sample_ticks=%u sample_count=%c" - " rest_ticks=%u pin_value=%c") - self._query_cmd = self._mcu.lookup_command("end_stop_query oid=%c") + " rest_ticks=%u pin_value=%c", cq=cmd_queue) + self._query_cmd = self._mcu.lookup_command("end_stop_query oid=%c", + cq=cmd_queue) self._mcu.register_msg(self._handle_end_stop_state, "end_stop_state" , self._oid) def home_prepare(self): @@ -176,10 +177,9 @@ class MCU_endstop: self._homing = True self._min_query_time = self._mcu.monotonic() self._next_query_time = self._min_query_time + self.RETRY_QUERY - msg = self._home_cmd.encode( - self._oid, clock, self._mcu.seconds_to_clock(sample_time), - sample_count, rest_ticks, 1 ^ self._invert) - self._mcu.send(msg, reqclock=clock, cq=self._cmd_queue) + self._home_cmd.send( + [self._oid, clock, self._mcu.seconds_to_clock(sample_time), + sample_count, rest_ticks, 1 ^ self._invert], reqclock=clock) for s in self._steppers: s.note_homing_start(clock) def home_wait(self, home_end_time): @@ -208,15 +208,13 @@ class MCU_endstop: for s in self._steppers: s.note_homing_end() self._homing = False - msg = self._home_cmd.encode(self._oid, 0, 0, 0, 0, 0) - self._mcu.send(msg, reqclock=0, cq=self._cmd_queue) + self._home_cmd.send([self._oid, 0, 0, 0, 0, 0]) raise self.TimeoutError("Timeout during endstop homing") if self._mcu.is_shutdown(): raise error("MCU is shutdown") if eventtime >= self._next_query_time: self._next_query_time = eventtime + self.RETRY_QUERY - msg = self._query_cmd.encode(self._oid) - self._mcu.send(msg, cq=self._cmd_queue) + self._query_cmd.send([self._oid]) return True def query_endstop(self, print_time): self._homing = False @@ -237,7 +235,6 @@ class MCU_digital_out: self._is_static = False self._max_duration = 2. self._last_clock = 0 - self._cmd_queue = mcu.alloc_command_queue() self._set_cmd = None def get_mcu(self): return self._mcu @@ -260,14 +257,13 @@ class MCU_digital_out: " max_duration=%d" % ( self._oid, self._pin, self._start_value, self._shutdown_value, self._mcu.seconds_to_clock(self._max_duration))) + cmd_queue = self._mcu.alloc_command_queue() self._set_cmd = self._mcu.lookup_command( - "schedule_digital_out oid=%c clock=%u value=%c") + "schedule_digital_out oid=%c clock=%u value=%c", cq=cmd_queue) def set_digital(self, print_time, value): clock = self._mcu.print_time_to_clock(print_time) - msg = self._set_cmd.encode( - self._oid, clock, (not not value) ^ self._invert) - self._mcu.send(msg, minclock=self._last_clock, reqclock=clock - , cq=self._cmd_queue) + self._set_cmd.send([self._oid, clock, (not not value) ^ self._invert], + minclock=self._last_clock, reqclock=clock) self._last_clock = clock def set_pwm(self, print_time, value): self.set_digital(print_time, value >= 0.5) @@ -285,7 +281,6 @@ class MCU_pwm: self._is_static = False self._last_clock = 0 self._pwm_max = 0. - self._cmd_queue = mcu.alloc_command_queue() self._set_cmd = None def get_mcu(self): return self._mcu @@ -304,6 +299,7 @@ class MCU_pwm: self._shutdown_value = max(0., min(1., shutdown_value)) self._is_static = is_static def build_config(self): + cmd_queue = self._mcu.alloc_command_queue() cycle_ticks = self._mcu.seconds_to_clock(self._cycle_time) if self._hardware_pwm: self._pwm_max = self._mcu.get_constant_float("PWM_MAX") @@ -322,7 +318,7 @@ class MCU_pwm: self._shutdown_value * self._pwm_max, self._mcu.seconds_to_clock(self._max_duration))) self._set_cmd = self._mcu.lookup_command( - "schedule_pwm_out oid=%c clock=%u value=%hu") + "schedule_pwm_out oid=%c clock=%u value=%hu", cq=cmd_queue) else: if (self._start_value not in [0., 1.] or self._shutdown_value not in [0., 1.]): @@ -341,15 +337,14 @@ class MCU_pwm: self._start_value >= 0.5, self._shutdown_value >= 0.5, self._mcu.seconds_to_clock(self._max_duration))) self._set_cmd = self._mcu.lookup_command( - "schedule_soft_pwm_out oid=%c clock=%u value=%hu") + "schedule_soft_pwm_out oid=%c clock=%u value=%hu", cq=cmd_queue) def set_pwm(self, print_time, value): clock = self._mcu.print_time_to_clock(print_time) if self._invert: value = 1. - value value = int(max(0., min(1., value)) * self._pwm_max + 0.5) - msg = self._set_cmd.encode(self._oid, clock, value) - self._mcu.send(msg, minclock=self._last_clock, reqclock=clock - , cq=self._cmd_queue) + self._set_cmd.send([self._oid, clock, value], + minclock=self._last_clock, reqclock=clock) self._last_clock = clock class MCU_adc: @@ -362,7 +357,6 @@ class MCU_adc: self._report_clock = 0 self._oid = self._callback = None self._inv_max_adc = 0. - self._cmd_queue = mcu.alloc_command_queue() def get_mcu(self): return self._mcu def setup_minmax(self, sample_time, sample_count, minval=0., maxval=1.): @@ -534,12 +528,12 @@ class MCU: self._config_crc = zlib.crc32('\n'.join(self._config_cmds)) & 0xffffffff self.add_config_cmd("finalize_config crc=%d" % (self._config_crc,)) def _send_config(self): - msg = self.create_command("get_config") + get_config_cmd = self.lookup_command("get_config") if self.is_fileoutput(): config_params = { 'is_config': 0, 'move_count': 500, 'crc': self._config_crc} else: - config_params = self.send_with_response(msg, 'config') + config_params = get_config_cmd.send_with_response(response='config') if not config_params['is_config']: if self._restart_method == 'rpi_usb': # Only configure mcu after usb power reset @@ -548,9 +542,10 @@ class MCU: logging.info("Sending MCU '%s' printer configuration...", self._name) for c in self._config_cmds: - self.send(self.create_command(c)) + self._serial.send(c) if not self.is_fileoutput(): - config_params = self.send_with_response(msg, 'config') + config_params = get_config_cmd.send_with_response( + response='config') if not config_params['is_config']: if self._is_shutdown: raise error("MCU '%s' error during config: %s" % ( @@ -579,7 +574,7 @@ class MCU: move_count) self._ffi_lib.steppersync_set_time(self._steppersync, 0., self._mcu_freq) for c in self._init_cmds: - self.send(self.create_command(c)) + self._serial.send(c) def _connect(self): if self.is_fileoutput(): self._connect_file() @@ -637,23 +632,19 @@ class MCU: def get_max_stepper_error(self): return self._max_stepper_error # Wrapper functions - def send(self, cmd, minclock=0, reqclock=0, cq=None): - self._serial.send(cmd, minclock, reqclock, cq=cq) - def send_with_response(self, cmd, name, oid=None): - return self._serial.send_with_response(cmd, name, oid) def register_msg(self, cb, msg, oid=None): self._serial.register_callback(cb, msg, oid) def alloc_command_queue(self): return self._serial.alloc_command_queue() - def create_command(self, msg): - return self._serial.msgparser.create_command(msg) - def lookup_command(self, msgformat): - return self._serial.msgparser.lookup_command(msgformat) + def lookup_command(self, msgformat, cq=None): + return self._serial.lookup_command(msgformat, cq) def try_lookup_command(self, msgformat): try: - return self._serial.msgparser.lookup_command(msgformat) + return self.lookup_command(msgformat) except self._serial.msgparser.error as e: return None + def lookup_command_id(self, msgformat): + return self._serial.msgparser.lookup_command(msgformat).msgid def get_constant_float(self, name): return self._serial.msgparser.get_constant_float(name) def print_time_to_clock(self, print_time): @@ -679,7 +670,7 @@ class MCU: def _shutdown(self, force=False): if self._emergency_stop_cmd is None or (self._is_shutdown and not force): return - self.send(self._emergency_stop_cmd.encode()) + self._emergency_stop_cmd.send() def _restart_arduino(self): logging.info("Attempting MCU '%s' reset", self._name) self._disconnect() @@ -695,11 +686,11 @@ class MCU: self._is_shutdown = True self._shutdown(force=True) self._reactor.pause(self._reactor.monotonic() + 0.015) - self.send(self._config_reset_cmd.encode()) + self._config_reset_cmd.send() else: # Attempt reset via reset command logging.info("Attempting MCU '%s' reset command", self._name) - self.send(self._reset_cmd.encode()) + self._reset_cmd.send() self._reactor.pause(self._reactor.monotonic() + 0.015) self._disconnect() def _restart_rpi_usb(self): diff --git a/klippy/msgproto.py b/klippy/msgproto.py index 3d655faa..7e38fe6a 100644 --- a/klippy/msgproto.py +++ b/klippy/msgproto.py @@ -108,7 +108,7 @@ class MessageFormat: self.param_types = [MessageTypes[fmt] for name, fmt in argparts] self.param_names = [(name, MessageTypes[fmt]) for name, fmt in argparts] self.name_to_type = dict(self.param_names) - def encode(self, *params): + def encode(self, params): out = [] out.append(self.msgid) for i, t in enumerate(self.param_types): diff --git a/klippy/serialhdl.py b/klippy/serialhdl.py index 6040f3ab..75c61346 100644 --- a/klippy/serialhdl.py +++ b/klippy/serialhdl.py @@ -126,17 +126,17 @@ class SerialReader: with self.lock: del self.handlers[name, oid] # Command sending - def send(self, cmd, minclock=0, reqclock=0, cq=None): + def raw_send(self, cmd, minclock, reqclock, cmd_queue): + self.ffi_lib.serialqueue_send( + self.serialqueue, cmd_queue, cmd, len(cmd), minclock, reqclock) + def send(self, msg, minclock=0, reqclock=0): + cmd = self.msgparser.create_command(msg) + self.raw_send(cmd, minclock, reqclock, self.default_cmd_queue) + def lookup_command(self, msgformat, cq=None): if cq is None: cq = self.default_cmd_queue - self.ffi_lib.serialqueue_send( - self.serialqueue, cq, cmd, len(cmd), minclock, reqclock) - def encode_and_send(self, data, minclock, reqclock, cq): - self.ffi_lib.serialqueue_encode_and_send( - self.serialqueue, cq, data, len(data), minclock, reqclock) - def send_with_response(self, cmd, name, oid=None): - src = SerialRetryCommand(self, cmd, name, oid) - return src.get_response() + cmd = self.msgparser.lookup_command(msgformat) + return SerialCommand(self, cq, cmd) def alloc_command_queue(self): return self.ffi_main.gc(self.ffi_lib.serialqueue_alloc_commandqueue(), self.ffi_lib.serialqueue_free_commandqueue) @@ -175,6 +175,20 @@ class SerialReader: def __del__(self): self.disconnect() +# Wrapper around command sending +class SerialCommand: + def __init__(self, serial, cmd_queue, cmd): + self.serial = serial + self.cmd_queue = cmd_queue + self.cmd = cmd + def send(self, data=(), minclock=0, reqclock=0): + cmd = self.cmd.encode(data) + self.serial.raw_send(cmd, minclock, reqclock, self.cmd_queue) + def send_with_response(self, data=(), response=None, response_oid=None): + cmd = self.cmd.encode(data) + src = SerialRetryCommand(self.serial, cmd, response, response_oid) + return src.get_response() + # Class to retry sending of a query command until a given response is received class SerialRetryCommand: TIMEOUT_TIME = 5.0 @@ -195,7 +209,7 @@ class SerialRetryCommand: def send_event(self, eventtime): if self.response is not None: return self.serial.reactor.NEVER - self.serial.send(self.cmd) + self.serial.raw_send(self.cmd, 0, 0, self.serial.default_cmd_queue) return eventtime + self.RETRY_TIME def handle_callback(self, params): last_sent_time = params['#sent_time'] @@ -217,7 +231,7 @@ class SerialBootStrap: def __init__(self, serial): self.serial = serial self.identify_data = "" - self.identify_cmd = self.serial.msgparser.lookup_command( + self.identify_cmd = self.serial.lookup_command( "identify offset=%u count=%c") self.is_done = False self.serial.register_callback(self.handle_identify, 'identify_response') @@ -241,13 +255,11 @@ class SerialBootStrap: self.is_done = True return self.identify_data += msgdata - imsg = self.identify_cmd.encode(len(self.identify_data), 40) - self.serial.send(imsg) + self.identify_cmd.send([len(self.identify_data), 40]) def send_event(self, eventtime): if self.is_done: return self.serial.reactor.NEVER - imsg = self.identify_cmd.encode(len(self.identify_data), 40) - self.serial.send(imsg) + self.identify_cmd.send([len(self.identify_data), 40]) return eventtime + self.RETRY_TIME def handle_unknown(self, params): logging.debug("Unknown message %d (len %d) while identifying",