serialhdl: Make SerialReader.send_with_response() blocking

Use the greenlet mechanism to wait for the response directly in the
send_with_response() method.  This simplifies the calling code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2016-11-28 14:52:22 -05:00
parent 535c7b99b4
commit a0829c63de
2 changed files with 35 additions and 45 deletions

View File

@ -337,10 +337,6 @@ class MCU:
self.serial.dump_debug() self.serial.dump_debug()
self._printer.shutdown() self._printer.shutdown()
# Connection phase # Connection phase
def _init_steppersync(self, count):
stepqueues = tuple(s._stepqueue for s in self._steppers)
self._steppersync = self.ffi_lib.steppersync_alloc(
self.serial.serialqueue, stepqueues, len(stepqueues), count)
def connect(self): def connect(self):
if not self._is_fileoutput: if not self._is_fileoutput:
self.serial.connect() self.serial.connect()
@ -351,13 +347,6 @@ class MCU:
def connect_file(self, debugoutput, dictionary, pace=False): def connect_file(self, debugoutput, dictionary, pace=False):
self._is_fileoutput = True self._is_fileoutput = True
self.serial.connect_file(debugoutput, dictionary) self.serial.connect_file(debugoutput, dictionary)
def dummy_send_config():
for c in self._config_cmds:
self.send(self.create_command(c))
self._init_steppersync(500)
for cb in self._init_callbacks:
cb()
self._send_config = dummy_send_config
if not pace: if not pace:
def dummy_set_print_start_time(eventtime): def dummy_set_print_start_time(eventtime):
pass pass
@ -416,31 +405,25 @@ class MCU:
self._send_config() self._send_config()
def _send_config(self): def _send_config(self):
msg = self.create_command("get_config") msg = self.create_command("get_config")
config_params = {} if self._is_fileoutput:
sent_config = False config_params = {
def handle_get_config(params): 'is_config': 0, 'move_count': 500, 'crc': self._config_crc}
config_params.update(params) else:
return True config_params = self.serial.send_with_response(msg, 'config')
while 1: if not config_params['is_config']:
self.serial.send_with_response(msg, handle_get_config, 'config') # Send config commands
while 1: for c in self._config_cmds:
is_config = config_params.get('is_config') self.send(self.create_command(c))
if is_config is not None and (not sent_config or is_config): if not self._is_fileoutput:
break config_params = self.serial.send_with_response(msg, 'config')
self._printer.reactor.pause(time.time() + 0.05) if self._config_crc != config_params['crc']:
if not is_config: logging.error("Printer CRC does not match config")
# Send config commands sys.exit(1)
for c in self._config_cmds:
self.send(self.create_command(c))
config_params.clear()
sent_config = True
continue
if self._config_crc != config_params['crc']:
logging.error("Printer CRC does not match config")
sys.exit(1)
break
logging.info("Configured") logging.info("Configured")
self._init_steppersync(config_params['move_count']) stepqueues = tuple(s._stepqueue for s in self._steppers)
self._steppersync = self.ffi_lib.steppersync_alloc(
self.serial.serialqueue, stepqueues, len(stepqueues),
config_params['move_count'])
for cb in self._init_callbacks: for cb in self._init_callbacks:
cb() cb()
# Config creation helpers # Config creation helpers

View File

@ -146,8 +146,9 @@ class SerialReader:
def encode_and_send(self, data, minclock, reqclock, cq): def encode_and_send(self, data, minclock, reqclock, cq):
self.ffi_lib.serialqueue_encode_and_send( self.ffi_lib.serialqueue_encode_and_send(
self.serialqueue, cq, data, len(data), minclock, reqclock) self.serialqueue, cq, data, len(data), minclock, reqclock)
def send_with_response(self, cmd, callback, name): def send_with_response(self, cmd, name):
SerialRetryCommand(self, cmd, callback, name) src = SerialRetryCommand(self, cmd, name)
return src.get_response()
def send_flush(self): def send_flush(self):
self.ffi_lib.serialqueue_flush_ready(self.serialqueue) self.ffi_lib.serialqueue_flush_ready(self.serialqueue)
def alloc_command_queue(self): def alloc_command_queue(self):
@ -207,25 +208,31 @@ class SerialReader:
# Class to retry sending of a query command until a given response is received # Class to retry sending of a query command until a given response is received
class SerialRetryCommand: class SerialRetryCommand:
RETRY_TIME = 0.500 RETRY_TIME = 0.500
def __init__(self, serial, cmd, callback, name): def __init__(self, serial, cmd, name):
self.serial = serial self.serial = serial
self.cmd = cmd self.cmd = cmd
self.callback = callback
self.name = name self.name = name
self.response = None
self.min_query_time = time.time()
self.serial.register_callback(self.handle_callback, self.name) self.serial.register_callback(self.handle_callback, self.name)
self.send_timer = self.serial.reactor.register_timer( self.send_timer = self.serial.reactor.register_timer(
self.send_event, self.serial.reactor.NOW) self.send_event, self.serial.reactor.NOW)
def send_event(self, eventtime): def send_event(self, eventtime):
if self.callback is None: if self.response is not None:
self.serial.reactor.unregister_timer(self.send_timer)
return self.serial.reactor.NEVER return self.serial.reactor.NEVER
self.serial.send(self.cmd) self.serial.send(self.cmd)
return eventtime + self.RETRY_TIME return eventtime + self.RETRY_TIME
def handle_callback(self, params): def handle_callback(self, params):
done = self.callback(params) last_sent_time = params['#sent_time']
if done: if last_sent_time >= self.min_query_time:
self.serial.unregister_callback(self.name) self.response = params
self.callback = None def get_response(self):
eventtime = time.time()
while self.response is None:
eventtime = self.serial.reactor.pause(eventtime + 0.05)
self.serial.unregister_callback(self.name)
self.serial.reactor.unregister_timer(self.send_timer)
return self.response
# Code to start communication and download message type dictionary # Code to start communication and download message type dictionary
class SerialBootStrap: class SerialBootStrap: