From 145303f35bdeb844346b2f085dbd89c5f1673731 Mon Sep 17 00:00:00 2001 From: David Rebbe Date: Thu, 29 Jan 2026 05:45:35 -0500 Subject: [PATCH] added stop and reset --- freewili/cli_serial.py | 42 ++++++++++++++++++++++++++++++- freewili/fw.py | 48 ++++++++++++++++++++++++++++++++++-- freewili/fw_serial.py | 56 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 142 insertions(+), 4 deletions(-) diff --git a/freewili/cli_serial.py b/freewili/cli_serial.py index 477f3a8..acfd53a 100644 --- a/freewili/cli_serial.py +++ b/freewili/cli_serial.py @@ -88,6 +88,13 @@ def main() -> None: const=False, help="Run a script on the FreeWili. If no argument is provided, -fn will be used.", ) + parser.add_argument( + "-y", + "--stop_script", + nargs="?", + const=True, + help="Stop any running script on the FreeWili.", + ) parser.add_argument( "-io", "--io", @@ -141,6 +148,13 @@ def main() -> None: nargs=1, help="Transmit subfile on selected radio. Name of the file (ie. yellow.sub)", ) + parser.add_argument( + "-r", + "--reset_software", + action="store_true", + default=False, + help="Reset the software on the FreeWili.", + ) parser.add_argument( "--version", action="version", @@ -243,6 +257,19 @@ def get_file_callback(msg: str) -> None: exit_with_error("Missing case statement") case Err(msg): exit_with_error(msg) + if args.stop_script: + match get_device(device_index, devices): + case Ok(device): + print("Stopping any running scripts...") + match device.stop_script(): + case Ok(msg): + print(f"Successfully stopped scripts: {msg}") + case Err(msg): + exit_with_error(f"Failed to stop scripts: {msg}") + case _: + raise RuntimeError("Missing case statement") + case Err(msg): + exit_with_error(msg) if args.run_script is not None: match get_device(device_index, devices): case Ok(device): @@ -255,7 +282,7 @@ def get_file_callback(msg: str) -> None: else: raise ValueError("No script or file name provided") print(f"Running script {script_name}...") - match device.run_script(script_name): + match device.run_script(script_name, True): case Ok(msg): print(f"Successfully ran script {script_name}: {msg}") case Err(msg): @@ -395,6 +422,19 @@ def get_file_callback(msg: str) -> None: exit_with_error(f"Failed to transmit radio file {value}: {msg}") case Err(msg): exit_with_error(msg) + if args.reset_software: + match get_device(device_index, devices): + case Ok(device): + print("Resetting software...") + match device.reset_software(FreeWiliProcessorType.Main if not processor_type else processor_type): + case Ok(msg): + print(f"Successfully reset software: {msg}") + case Err(msg): + exit_with_error(f"Failed to reset software {msg}") + case Err(msg): + exit_with_error(msg) + case Err(msg): + exit_with_error(msg) if __name__ == "__main__": diff --git a/freewili/fw.py b/freewili/fw.py index 038efe2..0800369 100644 --- a/freewili/fw.py +++ b/freewili/fw.py @@ -398,8 +398,50 @@ def user_callback(msg: str) -> None case _: raise RuntimeError("Missing case statement") + def reset_software(self, processor: FreeWiliProcessorType = FreeWiliProcessorType.Main) -> Result[str, str]: + """Run a script on the FreeWili. + + Arguments: + ---------- + processor: FreeWiliProcessorType + Processor to upload the file to. + + Returns: + --------- + Result[str, str]: + Ok(str) if the command was sent successfully, Err(str) if not. + """ + match self.get_serial_from(processor): + case Ok(serial): + return serial.reset_software() + case Err(msg): + return Err(msg) + case _: + raise RuntimeError("Missing case statement") + + def stop_script(self, processor: FreeWiliProcessorType = FreeWiliProcessorType.Main) -> Result[str, str]: + """Run a script on the FreeWili. + + Arguments: + ---------- + processor: FreeWiliProcessorType + Processor to upload the file to. + + Returns: + --------- + Result[str, str]: + Ok(str) if the command was sent successfully, Err(str) if not. + """ + match self.get_serial_from(processor): + case Ok(serial): + return serial.stop_script() + case Err(msg): + return Err(msg) + case _: + raise RuntimeError("Missing case statement") + def run_script( - self, file_name: str, processor: FreeWiliProcessorType = FreeWiliProcessorType.Main + self, file_name: str, stop_first: bool, processor: FreeWiliProcessorType = FreeWiliProcessorType.Main ) -> Result[str, str]: """Run a script on the FreeWili. @@ -407,6 +449,8 @@ def run_script( ---------- file_name: str Name of the file in the FreeWili. 8.3 filename limit exists as of V12 + stop_first: bool + Whether to stop any running scripts before starting the new one. processor: FreeWiliProcessorType Processor to upload the file to. @@ -417,7 +461,7 @@ def run_script( """ match self.get_serial_from(processor): case Ok(serial): - return serial.run_script(file_name) + return serial.run_script(file_name, stop_first) case Err(msg): return Err(msg) case _: diff --git a/freewili/fw_serial.py b/freewili/fw_serial.py index 9b31967..1c4e0d8 100644 --- a/freewili/fw_serial.py +++ b/freewili/fw_serial.py @@ -1136,7 +1136,54 @@ def record_audio(self, file_name: str) -> Result[str, str]: return self._handle_final_response_frame() @needs_open() - def run_script(self, file_name: str) -> Result[str, str]: + def reset_software(self) -> Result[str, str]: + """Soft reset the FreeWili. + + Arguments: + ---------- + None + + Returns: + ------- + Result[str, str]: + Ok(str) if the command was sent successfully, Err(str) if not. + """ + self._empty_all() + time.sleep(1) + self.serial_port.send("z\\n\n") + self.serial_port.close() + time.sleep(3.0) + return Ok("Software reset command sent. Please reconnect.") + + @needs_open() + def stop_script(self) -> Result[str, str]: + """Stop any running script on the FreeWili. + + Arguments: + ---------- + None + + Returns: + ------- + Result[str, str]: + Ok(str) if the command was sent successfully, Err(str) if not. + """ + self._empty_all() + # The blank after the y is required to stop all scripts + self.serial_port.send("y \n") + match self._handle_final_response_frame(): + case Ok(resp): + return Ok(resp) + case Err(msg): + # As of v91 firmware the response frame reports back 0 for success + if msg.lower == "ok": + return Ok(msg) + return Ok(msg) + case _: + raise RuntimeError("Missing case statement") + + @needs_open() + def run_script(self, file_name: str, stop_first: bool) -> Result[str, str]: """Run a script on the FreeWili. Arguments: @@ -1144,12 +1191,19 @@ def run_script(self, file_name: str) -> Result[str, str]: file_name: str Name of the file in the FreeWili. 8.3 filename limit exists as of V12 + stop_first: bool + Whether to stop any running scripts before starting the new one. + Returns: ------- Result[str, str]: Ok(str) if the command was sent successfully, Err(str) if not. """ self._empty_all() + if stop_first: + # The blank after the y is required to stop all scripts + self.serial_port.send("y \n") + self._wait_for_response_frame(2.0) cmd = f"w\n{file_name}" self.serial_port.send(cmd) match self._wait_for_response_frame(2.0):