diff --git a/src/main/python/ayab/engine/communication.py b/src/main/python/ayab/engine/communication.py index f25f077e..4aa0b3a4 100644 --- a/src/main/python/ayab/engine/communication.py +++ b/src/main/python/ayab/engine/communication.py @@ -54,6 +54,8 @@ class Token(Enum): autoCmd = 0x2A testCmd = 0x2B quitCmd = 0x2C + reqQuit = 0x0C + cnfQuit = 0xCC reqInit = 0x05 cnfInit = 0xC5 setCmd = 0x2D @@ -160,8 +162,19 @@ def req_init_API6(self, machine: Machine) -> None: data = self.__driver.send(bytes(data)) self.__ser.write(data) - def quit_API6(self) -> None: - """Send a quit message to the device.""" + def req_quit_knit_API6(self) -> None: + """Send a quit knit message to the device.""" + if self.__ser is None: + return + data = bytearray() + data.append(Token.reqQuit.value) + data = self.__driver.send(bytes(data)) + self.__ser.write(data) + + def req_quit_test_API6(self) -> None: + """Send a quit test message to the device.""" + if self.__ser is None: + return data = bytearray() data.append(Token.quitCmd.value) data = self.__driver.send(bytes(data)) diff --git a/src/main/python/ayab/engine/communication_mock.py b/src/main/python/ayab/engine/communication_mock.py index 33080304..ea902009 100644 --- a/src/main/python/ayab/engine/communication_mock.py +++ b/src/main/python/ayab/engine/communication_mock.py @@ -94,6 +94,16 @@ def req_start_API6( cnfStart = bytes([Token.cnfStart.value, 0]) self.rx_msg_list.append(cnfStart) + def req_quit_knit_API6(self): + """Send a quit knit message to the device.""" + cnfQuit = bytes([Token.reqQuit.value, 0]) + self.rx_msg_list.append(cnfQuit) + + def req_quit_test_API6(self): + """Send a quit test message to the device.""" + cnfQuit = bytes([Token.quitCmd.value, 0]) + self.rx_msg_list.append(cnfQuit) + def cnf_line_API6(self, line_number, color, flags, line_data) -> bool: """Send a row of stitch data.""" return True diff --git a/src/main/python/ayab/engine/engine.py b/src/main/python/ayab/engine/engine.py index 8f36dc2d..0109f61f 100644 --- a/src/main/python/ayab/engine/engine.py +++ b/src/main/python/ayab/engine/engine.py @@ -178,22 +178,25 @@ def run(self, operation: Operation) -> None: if self.__canceled or self.control.state == State.FINISHED: break - self.control.stop() - + # TODO: provide translations for these messages if operation == Operation.KNIT: if self.__canceled: + self.control.state = State.CANCEL_KNIT self.emit_notification("Knitting canceled.") self.__logger.info("Knitting canceled.") + self.control.operate(operation) else: - # operation == Operation.TEST: self.__logger.info("Finished knitting.") # small delay to finish printing to knit progress window # before "finish.wav" sound plays sleep(1) else: - # TODO: provide translations for these messages + # operation == Operation.TEST: self.__logger.info("Finished testing.") + # stop serial communication + self.control.stop() + # send signal to finish operation # "finish.wav" sound only plays if knitting was not canceled self.emit_operation_finisher(operation, not self.__canceled) diff --git a/src/main/python/ayab/engine/engine_fsm.py b/src/main/python/ayab/engine/engine_fsm.py index 4668a421..17936b66 100644 --- a/src/main/python/ayab/engine/engine_fsm.py +++ b/src/main/python/ayab/engine/engine_fsm.py @@ -45,19 +45,20 @@ class State(Enum): CONNECT = auto() VERSION_CHECK = auto() INIT = auto() - REQUEST_START = auto() - CONFIRM_START = auto() + REQUEST_KNIT = auto() + CONFIRM_KNIT = auto() RUN_KNIT = auto() + CANCEL_KNIT = auto() REQUEST_TEST = auto() CONFIRM_TEST = auto() RUN_TEST = auto() + CANCEL_TEST = auto() FINISHED = auto() class StateMachine(QStateMachine): """ Each method is a step in the finite state machine that governs serial - M communication with the device and is called only by `Control.operate()` @author Tom Price @@ -130,8 +131,8 @@ def _API6_init(control: Control, operation: Operation) -> Output: return Output.NONE else: # operation = Operation.KNIT: - control.state = State.REQUEST_START - control.logger.debug("State REQUEST_START") + control.state = State.REQUEST_KNIT + control.logger.debug("State REQUEST_KNIT") return Output.NONE else: control.logger.error("Error initializing firmware: " + str(param)) @@ -141,7 +142,7 @@ def _API6_init(control: Control, operation: Operation) -> Output: return Output.INITIALIZING_FIRMWARE @staticmethod - def _API6_request_start(control: Control, operation: Operation) -> Output: + def _API6_request_knit(control: Control, operation: Operation) -> Output: token, param = control.check_serial_API6() if token == Token.indState: if param == 0: @@ -158,8 +159,8 @@ def _API6_request_start(control: Control, operation: Operation) -> Output: control.continuous_reporting, control.prefs.value("disable_hardware_beep"), ) - control.state = State.CONFIRM_START - control.logger.debug("State CONFIRM_START") + control.state = State.CONFIRM_KNIT + control.logger.debug("State CONFIRM_KNIT") else: # any value of param other than 0 is some kind of error code control.logger.debug( @@ -172,7 +173,7 @@ def _API6_request_start(control: Control, operation: Operation) -> Output: return Output.WAIT_FOR_INIT @staticmethod - def _API6_confirm_start(control: Control, operation: Operation) -> Output: + def _API6_confirm_knit(control: Control, operation: Operation) -> Output: token, param = control.check_serial_API6() if token == Token.cnfStart: if param == 0: @@ -203,6 +204,13 @@ def _API6_run_knit(control: Control, operation: Operation) -> Output: # else return Output.NONE + @staticmethod + def _API6_cancel_knit(control: Control, operation: Operation) -> Output: + control.logger.debug("State CANCEL_KNIT") + control.com.req_quit_knit_API6() + control.state = State.FINISHED + return Output.NONE + @staticmethod def _API6_request_test(control: Control, operation: Operation) -> Output: token, param = control.check_serial_API6() @@ -251,6 +259,13 @@ def _API6_run_test(control: Control, operation: Operation) -> Output: control.logger.debug("Token " + token.name + ", param " + str(param)) return Output.NONE + @staticmethod + def _API6_cancel_test(control: Control, operation: Operation) -> Output: + control.logger.debug("State CANCEL_TEST") + control.com.req_quit_test_API6() + control.state = State.FINISHED + return Output.NONE + @staticmethod def _API6_finished(control: Control, operation: Operation) -> Output: control.logger.debug("State FINISHED") diff --git a/src/main/python/ayab/hw_test.py b/src/main/python/ayab/hw_test.py index de2f0e61..67023471 100644 --- a/src/main/python/ayab/hw_test.py +++ b/src/main/python/ayab/hw_test.py @@ -118,13 +118,12 @@ def output(self, msg): def hideEvent(self, event): self.__timer.stop() self.__console.setPlainText("") - assert self.__control.state == State.FINISHED + self.__control.state = State.FINISHED self.accept() def reject(self): - # send quitCmd - self.__control.com.quit_API6() - self.__control.state = State.FINISHED + # cancel operation + self.__control.com.req_quit_test_API6() # reset dialog self._auto_button.setChecked(False) self._test_button.setChecked(False)