Skip to content

Commit

Permalink
Add canceled state to engine FSM
Browse files Browse the repository at this point in the history
  • Loading branch information
t0mpr1c3 committed Apr 15, 2024
1 parent c1b2969 commit 808f9d0
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 19 deletions.
17 changes: 15 additions & 2 deletions src/main/python/ayab/engine/communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class Token(Enum):
autoCmd = 0x2A
testCmd = 0x2B
quitCmd = 0x2C
reqQuit = 0x0C
cnfQuit = 0xCC
reqInit = 0x05
cnfInit = 0xC5
setCmd = 0x2D
Expand Down Expand Up @@ -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))
Expand Down
10 changes: 10 additions & 0 deletions src/main/python/ayab/engine/communication_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 7 additions & 4 deletions src/main/python/ayab/engine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
33 changes: 24 additions & 9 deletions src/main/python/ayab/engine/engine_fsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand All @@ -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:
Expand All @@ -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(
Expand All @@ -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:
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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")
Expand Down
7 changes: 3 additions & 4 deletions src/main/python/ayab/hw_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 808f9d0

Please sign in to comment.