diff --git a/buzzer_tool/buzzer.py b/buzzer_tool/buzzer.py index f64b813..ef2bcd1 100644 --- a/buzzer_tool/buzzer.py +++ b/buzzer_tool/buzzer.py @@ -3,7 +3,7 @@ import argparse import sys from core.config import load_config from core.connection import BuzzerConnection, BuzzerError -from core.commands import info, ls, put, mkdir, rm +from core.commands import info, ls, put, mkdir, rm, confirm, reboot def main(): parser = argparse.ArgumentParser(description="Edis Buzzer Host Tool") @@ -73,7 +73,11 @@ def main(): elif args.command == "mkdir": mkdir.execute(conn, path=args.path) elif args.command == "rm": - rm.execute(conn, path=args.path, recursive=args.recursive) + rm.execute(conn, path=args.path, recursive=args.recursive) + elif args.command == "confirm": + confirm.execute(conn) + elif args.command == "reboot": + reboot.execute(conn) elif args.command == "info" or args.command is None: # Wurde kein Befehl oder explizit 'info' angegeben, sind wir hier schon fertig pass diff --git a/buzzer_tool/core/commands/rm.py b/buzzer_tool/core/commands/rm.py index cc999f4..fb69872 100644 --- a/buzzer_tool/core/commands/rm.py +++ b/buzzer_tool/core/commands/rm.py @@ -1,4 +1,6 @@ # core/commands/rm.py +import fnmatch +import posixpath from core.connection import BuzzerError from core.commands.ls import get_file_tree @@ -21,10 +23,37 @@ def _try_rm(conn, path, is_dir=False): print(f" ❌ Fehler bei {path}: {e}") def execute(conn, path: str, recursive: bool = False): - """Löscht eine Datei oder ein Verzeichnis.""" + """Löscht eine Datei, ein Verzeichnis oder löst Wildcards (*) auf.""" + + # 1. Wildcard-Behandlung (z.B. /lfs/a/* oder *.wav) + if '*' in path or '?' in path: + dirname, pattern = posixpath.split(path) + if not dirname: + dirname = "/" + + print(f"Suche nach Dateien passend zu '{pattern}' in '{dirname}'...") + tree = get_file_tree(conn, target_path=dirname, recursive=False) + + # Fehler beim Verzeichnis-Lesen abfangen + if len(tree) == 1 and tree[0].get("type") == "E": + print(f"❌ Verzeichnis '{dirname}' nicht gefunden.") + return + + # Filtern mit fnmatch (funktioniert wie in der Linux-Shell) + matches = [node for node in tree if node.get("type") == "F" and fnmatch.fnmatch(node["name"], pattern)] + + if not matches: + print(f"Keine passenden Dateien für '{path}' gefunden.") + return + + for match in matches: + _try_rm(conn, match["path"], is_dir=False) + + return # Fertig mit Wildcard-Löschen + + # 2. Rekursives Löschen (-r) if recursive: print(f"Sammle Dateibaum für rekursives Löschen von '{path}'...") - # Lade den kompletten Baum ab diesem Pfad tree = get_file_tree(conn, target_path=path, recursive=True) if len(tree) == 1 and tree[0].get("type") == "E": @@ -36,7 +65,7 @@ def execute(conn, path: str, recursive: bool = False): else: _delete_recursive(conn, tree) - # Am Ende das eigentliche Ziel löschen (die Datei oder den nun leeren Ordner) + # 3. Standard-Löschen (Einzeldatei oder am Ende der Rekursion der leere Ordner) try: conn.send_command(f"rm {path}") print(f"🗑️ '{path}' erfolgreich gelöscht.") diff --git a/firmware/VERSION b/firmware/VERSION index 1e4a188..53d9f1c 100644 --- a/firmware/VERSION +++ b/firmware/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 0 VERSION_MINOR = 0 -PATCHLEVEL = 9 +PATCHLEVEL = 12 VERSION_TWEAK = 0 EXTRAVERSION = 0 \ No newline at end of file diff --git a/firmware/src/main.c b/firmware/src/main.c index 40b619c..5cfbc5e 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -48,10 +48,17 @@ int main(void) LOG_INF("All subsystems initialized. Starting application threads."); audio_system_ready(); - k_sleep(K_SECONDS(5)); // Kurze Pause, damit die READY-Antworten der Subsysteme noch rausgehen - volatile uint32_t *invalid_pointer = (volatile uint32_t *)0xFFFFFFFF; - *invalid_pointer = 0xDEADBEEF; - while (1) { + if (!boot_is_img_confirmed()) + { + LOG_INF("Confirmation of firmware image pending. Inform user..."); + audio_play("/lfs/sys/update"); + } + else + { + LOG_INF("Firmware image already confirmed. No need to confirm again."); + } + while (1) + { k_sleep(K_FOREVER); } } \ No newline at end of file diff --git a/firmware/src/protocol.c b/firmware/src/protocol.c index 8cd3e89..5bd5095 100644 --- a/firmware/src/protocol.c +++ b/firmware/src/protocol.c @@ -267,6 +267,26 @@ int rm(const char *path) { return rc; } +int confirm_firmware() { + int rc = boot_write_img_confirmed(); + if (rc < 0) + { + LOG_ERR("Failed to confirm firmware: %d", rc); + return rc; + } + LOG_INF("Firmware confirmed successfully"); + return 0; +} + +int reboot_device() { + LOG_INF("Rebooting device as requested by host..."); + send_ok(); + k_sleep(K_MSEC(100)); // Kurze Pause, damit die OK-Antwort noch rausgeht + while (log_process()); + sys_reboot(SYS_REBOOT_COLD); + return 0; // Dieser Code wird nie erreicht, aber wir geben ihn der Vollständigkeit halber zurück +} + void execute_current_command(void) { int rc; @@ -346,6 +366,24 @@ void execute_current_command(void) send_error(rc); } break; + case CMD_CONFIRM: + LOG_DBG("Executing CONFIRM command"); + rc = confirm_firmware(); + if (rc == 0) + { send_ok(); + } + else + { + send_error(rc); + } + break; + case CMD_REBOOT: + LOG_DBG("Executing REBOOT command"); + rc = reboot_device(); + if (rc != 0) { + send_error(rc); + } + break; default: LOG_ERR("No execution logic for command %d", current_command); send_error(ENOSYS); @@ -396,6 +434,14 @@ protocol_state_t reading_command(uint8_t byte) { LOG_DBG("Received RM command"); current_command = CMD_RM; + } else if (strcmp((char *)buffer, "confirm") == 0) + { + LOG_DBG("Received CONFIRM command"); + current_command = CMD_CONFIRM; + } else if (strcmp((char *)buffer, "reboot") == 0) + { + LOG_DBG("Received REBOOT command"); + current_command = CMD_REBOOT; } else { diff --git a/firmware/src/protocol.h b/firmware/src/protocol.h index 503a4b7..0b148e2 100644 --- a/firmware/src/protocol.h +++ b/firmware/src/protocol.h @@ -15,6 +15,8 @@ typedef enum { CMD_PUT_BINARY_FILE, CMD_MKDIR, CMD_RM, + CMD_CONFIRM, + CMD_REBOOT, /* Weitere Kommandos folgen hier */ } protocol_cmd_t;