Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue Quit command when knitting is cancelled #632

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 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,6 +162,24 @@ def req_init_API6(self, machine: Machine) -> None:
data = self.__driver.send(bytes(data))
self.__ser.write(data)

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))
self.__ser.write(data)

def cnf_line_API6(
self, line_number: int, color: int, flags: int, line_data: bytes
) -> None:
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
10 changes: 3 additions & 7 deletions src/main/python/ayab/hw_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +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
payload = bytearray()
token = Token.quitCmd.value
payload.append(token)
self.__control.com.write_API6(payload)
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
Loading