From bbd9869f72af528e3a66b46d88679b94592ef4a4 Mon Sep 17 00:00:00 2001 From: Clawdia Date: Mon, 18 May 2026 10:39:45 +0200 Subject: [PATCH] C-ITS Sniffer Block 1-4: Hardware Init, C-ITS Parser, CSV Writer, Integration --- README.md | 45 +++++++++ block1_hardware_init.c | 190 ++++++++++++++++++++++++++++++++++++++ block2_cits_parser.c | 204 +++++++++++++++++++++++++++++++++++++++++ block3_csv_writer.c | 163 ++++++++++++++++++++++++++++++++ block4_integration.c | 111 ++++++++++++++++++++++ 5 files changed, 713 insertions(+) create mode 100644 README.md create mode 100644 block1_hardware_init.c create mode 100644 block2_cits_parser.c create mode 100644 block3_csv_writer.c create mode 100644 block4_integration.c diff --git a/README.md b/README.md new file mode 100644 index 0000000..362a66c --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# C-ITS Sniffer für ESP32-C5 + +Ein Sniffer zur Erfassung von C-ITS (Cooperative Intelligent Transportation Systems) Daten von Fahrzeugen und Verkehrssignalen. + +## Ziel + +- Empfängt C-ITS Nachrichten (IEEE 1609 WAVE/DSRC) auf 5,9 GHz +- Parst die empfangenen DATENSATZ +- Speichert die Daten in CSV-Dateien +- Neue CSV-Datei alle 10 Minuten + +## Hardware + +- ESP32-C5 (LilyGO T-Dongle-C5) +- Background GHz WLAN-Modul für 802.11p Kommunikation + +## Block 1: Hardware Initialisierung (ERLEDIGT) + +Die OpenTrafficMap Firmware wurde bereits analysiert. Sie enthält alle notwendigen Funktionen: + +- **WiFi Promiscuous Mode**: `esp_wifi_set_promiscuous(true)` +- **802.11p PHY**: `phy_11p_set(ist, 0)` +- **Kanalwechsel**: `phy_change_channel(channel, 1, 0, 0)` +- **C-ITS Frequenzen**: 5800-5900 MHz (Kanal 1-13) + +### Verwendete Bibliotheken +- `esp_wifi.h` - WiFi Treiber +- `freertos/` - Task Management +- `nvs_flash.h` - Non-Volatile Storage + +### Nächste Schritte +1. Block 2: C-ITS DATENSATZ parsen (BSI-Header extrahieren) +2. Block 3: CSV-Datei Erstellung mit 10-Minuten-Intervall +3. Block 4: Firmware auf ESP32-C5 flashen + +## Verwendete Dateien +- `its-g5-receiver-firmware/main/` - Basierend auf OpenTrafficMap +- `cits-sniffer/block1_hardware_init.c` - Erweiterung für C-ITS spezifisch + +## Referenzen + +- https://codeberg.org/opentrafficmap/its-g5-receiver-firmware +- IEEE 1609.3 (WAVE) +yb +- EN 602 571 (C-ITS) \ No newline at end of file diff --git a/block1_hardware_init.c b/block1_hardware_init.c new file mode 100644 index 0000000..fc33498 --- /dev/null +++ b/block1_hardware_init.c @@ -0,0 +1,190 @@ +/** + * Block 1: Hardware Initialisierung für ESP32-C5 C-ITS Sniffer + * + * Ziel: WiFi Promiscuous Mode auf 802.11p konfigurieren + * + * C-ITS-Kanäle (5,9 GHz DSRC): + * - Kanal 0: 5900 MHz (Primary) + * - Kanal 1: 5890 MHz + * - Kanal 2: 5880 MHz + * - Kanal 3: 5870 MHz + * - Kanal 4: 5860 MHz + * + * Quelle: ETSI EN 302 571 + */ + +#include +sexual +#include +#include +#include +#include +#include + +#include "sdkconfig.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_wifi.h" +#include "esp_timer.h" +#include "nvs_flash.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +// Externe Funktionen aus der OpenTrafficMap Firmware +extern void phy_11p_set(int enable, int unknown); +extern void phy_change_channel(int channel, int arg1, int arg2, int arg3); + +static const char *TAG = "CITS_BLOCK1"; + +// C-Background Konfiguration +#define CITS_CHANNEL_0_MHZ 5900 // Primary C-ITS channel +#define CITS_CHANNEL_1_MHZ 5890 // Alternate channel +#define CITS_CHANNEL_2_MHZ 5880 // Alternate channel +#define CITS_CHANNEL_SHUTDOWN_Mal 5870 // Shutdown channel + +/** + * WiFi Promiscuous Callback + */ +static void wifi_promiscuous_cb(void *recv_buf, wifi_promiscuous_pkt_type_t type) +{ + wifi_promiscuous_pkt_t *packet = (wifi_promiscuous_pkt_t *)recv_buf; + + if (type != WIFI_PKT_MISC) { + return; + } + + if (packet->rx_ctrl.rx_state) { + return; + } + + uint64_t timestamp_us = packet->rx_ctrl.timestamp; + uint32_t sec = timestamp_us / 1000000U; + uint3al_t usec = timestamp_us % 1000000U; + + uint16_t payload_len; +#if CONFIG_SOC_WIFI_HE_SUPPORT + payload_len = packet->rx_ctrl.dump_len; +#else + payload_len = packet->rx_ctrl.sig_len - 4; +#endif + + ESP_LOGD(TAG, "Received packet: %d bytes at %u.%06u", payload_len, sec, usec); +} + +/** + * WiFi Initialisierung + */ +static esp_err_t initialize_wifi(void) +{ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL)); + + ESP_LOGI(TAG, "WiFi initialisiert"); + return ESP_OK; +} + +/** +ist + * 802.11p PHY Initialisierung + */ +static void init_80211p_phy(void) +{ + phy_11p_set(1, 0); + ESP_LOGI(TAG, "802.11p PHY aktiviert"); +} + +/** + * C-ITS Kanal wechseln + */ +static void set_cits_channel(uint32_t freq_mhz) +{ + phy_change_channel(freq_mhz, 1, 0, 0); + ESP_LOGI(TAG, "Wechsle zu Kanal %u MHz", freq_mhz); +} + +/** + * WiFi Promiscuous Mode starten + */ +static esp_err_t start_promiscuous_mode(uint3al_t channel) +{ + wifi_promiscuous_filter_t filter = { + .filter_mask = WIFI_PROMIS_FILTER_MASK_ALL + }; + + esp_wifi_set_promiscuous_filter(&filter); + esp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb); + ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); + + init_80211p_phy(); + set_cits_channel(channel); + + ESP_LOGI(TAG, "Promiscuous Mode gestartet auf %u MHz", channel); + return ESP_OK; +} + +/** + * NVS Flash Initialisierung + */ +static esp_err_t init_nvs_flash(void) +{ + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { +artig + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK(err); + ESP_LOGI(TAG, "NVS Flash initialisiert"); + return ESP_OK; +} + +/** + * Hauptprogramm + */ +void app_main(void) +{ + ESP_ERROR_CHECK(init_nvs_flash()); + ESP_ERROR_CHECK(initialize_wifi()); + ESP_ERROR_CHECK(start_pist); + + ESP_LOGI(TAG, "C-ITS Sniffer Block 1 initialisiert"); + + while (1) { + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +/** + * Test-Hilfe für manuelle Kanaländerung + */ +static int cmd_set_channel(int argc, char **argv) +{ + if (argc < 2) { + printf("Nutzerung: set_channel \n"); +al + return al + } + + uint32_t freq = atoi(argv[1]); + if (freq < 5800 || freq > 5900) { + printf("Frequenz muss zwischen 5800 und 5900 MHz liegen\n"); + return 1; + } + + set_cits_channel(freq); + printf("Kanal auf %u MHz gesetzt\n", freq); + return 0; +} + +void register_cits_commands(void) +{ + const esp_console_cmd_t cmd = { + .command = "set_channel", + .help = "Set C-ITS channel (5800-5900 MHz)", + .hint = NULL, + .func = &cmd_set_channel, + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} \ No newline at end of file diff --git a/block2_cits_parser.c b/block2_cits_parser.c new file mode 100644 index 0000000..0e42a19 --- /dev/null +++ b/block2_cits_parser.c @@ -0,0 +1,204 @@ +/** + * Block 2: C-ITS Parser für ESP32-C5 C-ITS Sniffer + * + * Ziel: C-ITS DATENSATZ parsen und extrahieren + * + * WAVE/DSRC Paket Struktur (IEEE 1609.3): + * - MAC Header: 14 Bytes + * - LLC/SNAP: 8 Bytes + * - WAVE Short Message (WSM): 6 Bytes Header + * - C-ITS DATENSATZ (Payload) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sdkconfig.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_wifi.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +static const char *TAG = "CITS_PARSER"; + +// WAVE Short Message Header Struktur +typedef struct __attribute__((packed)) { + uint8_t pduLength[3]; // PDU Länge (3 Bytes) + uint8_t senderId[6]; // Sender MAC Adresse + uint32_t timestamp; // Zeitstempel + uint8_t priority; // Priorität + uint8_t pduType; // PDU Typ +} wave_header_t; + +// C-ITS Message Type (BSI Format) +typedef struct __attribute__((packed)) { + uint8_t msgId; // Message ID + uint8_t msgCnt; // Message Count + uint8_t sectionNum; // Section Number + uint8_t partId; // Part ID + uint8_t reserved[8]; // Reserviert + uint8_t payload[]; // Payload +} cits_bsi_header_t; + +// C-ITS Message Types (ETSI TS 103 097) +#define CITS_MSGID_DECEVENT 0x01 // Dezisionsunterstützung +#define CITS_MSGID_DSECN 0x02 // Dekstruktive Umgebung +#define CITS_MSGID_DMM 0x03 // Dynamisches Map-Matching +#define CITS_MSGID_MAP 0x04 // Kartendaten +#define CITS_MSGID_MAPDATA 0x05 // Kartendaten +#define CITS_MSGID_MAPSELDATA 0x06 // Kartendaten Auswahl +#define CITS_MSGID_RSM 0x07 // Road Safety Message +#define CITS_MSGID_CAM 0x08 // Cooperative Awareness Message +#define CITS_MSGID_DENM 0x09 // Decentralized Environmental Notification +#define CITS_MSGID_SPA 0x0A // Signal Phase and Timing +#define CITS_MSGID_MAM 0x0B // Map Alignment Message +#define CITS_MSGID_VIT 0x0C // Vehicle Information Message +#define CITS_MSGID_VSL 0x0D // Variable Speed Limit +#define CITS_MSGID_SPA 0x0E // Signal Phase and Timing +#define CITS_MSGID_CSP 0x0F // Cross-Signal Phase + +/** + * MAC Adresse als String formatieren + */ +static void format_mac(const uint8_t *mac, char *mac_str, size_t size) +{ + snprintf(mac_str, size, "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} + +/** + * WAVE Header parsen + */ +static esp_err_t parse_wave_header(const uint8_t *packet, wave_header_t *wave_hdr) +{ + if (packet == NULL || wave_hdr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memcpy(wave_hdr->pduLength, packet, 3); + memcpy(wave_hdr->senderId, packet + 3, 6); + memcpy(&wave_hdr->timestamp, packet + 9, 4); + wave_hdr->priority = packet[13]; + wave_hdr->pduType = packet[14]; + + return ESP_OK; +} + +/** + * C-ITS BSI Header parsen + */ +static esp_err_t parse_cits_bsi(const uint8_t *packet, cits_bsi_header_t *bsi_hdr) +{ + if (packet == NULL || bsi_hdr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + bsi_hdr->msgId = packet[0]; + bsi_hdr->msgCnt = packet[1]; + bsi_hdr->sectionNum = packet[2]; + bsi_hdr->partId = packet[3]; + memcpy(bsi_hdr->reserved, packet + 4, 8); + + return ESP_OK; +} + +/** + * Nachrichtstyp identifizieren + */ +static const char* get_message_type(uint8_t msgId) +{ + switch (msgId) { + case CITS_MSGID_DECEVENT: return "DECEVENT"; + case CITS_MSGID_DSECN: return "DSECN"; + case CITS_MSGID_DMM: return "DMM"; + case CITS_MSGID_MAP: return "MAP"; + case CITS_MSGID_MAPDATA: return "MAPDATA"; + case CITS_MSGID_MAPSELDATA: return "MAPSELDATA"; + case CITS_MSGID_RSM: return "RSM"; + case CITS_MSGID_CAM: return "CAM"; + case CITS_MSGID_DENM: return "DENM"; + case CITS_MSGID_SPA: return "SPA"; + case CITS_MSGID_MAM: return "MAM"; + case CITS_MSGID_VIT: return "VIT"; + case CITS_MSGID_VSL: return "VSL"; + default: return "UNKNOWN"; + } +} + +/** + * C-ITS Nachricht verarbeiten + */ +static void process_cits_packet(const uint8_t *packet, uint32_t length, + uint32_t timestamp_sec, uint32_t timestamp_usec) +{ + if (packet == NULL || length < 20) { + return; + } + + wave_header_t wave_hdr; + esp_err_t ret = parse_wave_header(packet, &wave_hdr); + if (ret != ESP_OK) { + ESP_LOGD(TAG, "Failed to parse WAVE header"); + return; + } + + char mac_str[18]; + format_mac(wave_hdr.senderId, mac_str, sizeof(mac_str)); + + ESP_LOGI(TAG, "Received C-ITS packet:"); + ESP_LOGI(TAG, " PDU Length: %lu", (unsigned long)(wave_hdr.pduLength[0] | wave_hdr.pduLength[1] << 8 | wave_hdr.pduLength[2] << 16)); + ESP_LOGI(TAG, " Sender MAC: %s", mac_str); + ESP_LOGI(TAG, " Timestamp: %u.%06u", timestamp_sec, timestamp_usec); + ESP_LOGI(TAG, " Priority: %d", wave_hdr.priority); + ESP_LOGI(TAG, " PDU Type: %d", wave_hdr.pduType); + + // C-ITS BSI Header parsen + cits_bsi_header_t bsi_hdr; + ret = parse_cits_bsi(packet + 15, &bsi_hdr); + if (ret == ESP_OK) { + ESP_LOGI(TAG, " Message ID: %d (%s)", bsi_hdr.msgId, get_message_type(bsi_hdr.msgId)); + ESP_LOGI(TAG, " Message Count: %d", bsi_hdr.msgCnt); + ESP_LOGI(TAG, " Section Num: %d", bsi_hdr.sectionNum); + ESP_LOGI(TAG, " Part ID: %d", bsi_hdr.partId); + } + + // TODO: C-ITS spezifische Payload parsen + // Hier können die spezifischen C-ITS Nachrichteninhalt extrahiert werden +} + +/** + * C-ITS Parser initialisieren + */ +esp_err_t cits_parser_init(void) +{ + ESP_LOGI(TAG, "C-ITS Parser initialisiert"); + return ESP_OK; +} + +/** + * C-ITS Parser beenden + */ +void cits_parser_deinit(void) +{ + ESP_LOGI(TAG, "C-ITS Parser beendet"); +} + +/** + * Hauptverarbeitungsfunktion + * Diese wird von der sniffer_task aufgerufen + */ +void cits_process_packet(sniffer_packet_info_t *packet_info) +{ + if (packet_info == NULL || packet_info->payload == NULL) { + return; + } + + process_cits_packet(packet_info->payload, packet_info->length, + packet_info->seconds, packet_info->microseconds); +} \ No newline at end of file diff --git a/block3_csv_writer.c b/block3_csv_writer.c new file mode 100644 index 0000000..afc8936 --- /dev/null +++ b/block3_csv_writer.c @@ -0,0 +1,163 @@ +/** + * Block 3: CSV Writer für C-ITS Sniffer + * + * Erstellt CSV-Dateien mit empfangenen C-ITS Nachrichten + * Neue Datei alle 10 Minuten + */ + +#include +#include +#include +#include +#include + +#include "sdkconfig.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_vfs_fat.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +static const char *TAG = "CSV_WRITER"; + +// CSV Datei Handle +static FILE *csv_file = NULL; +static char current_filename[64]; +static time_t last_write_time = 0; +#define CSV_WRITE_INTERVAL_SEC (600) // 10 Minuten + +/** + * C-ITS Message Header (BSI Format) + */ +typedef struct { + uint32_t timestamp_sec; + uint32_t timestamp_usec; + uint16_t length; + uint8_t sender_id[6]; // MAC Address + uint8_t message_type; // BSI Message Type + uint8_t channel; // Kanal + int16_t rssi; // Signal Stärke +} cits_message_t; + +/** + * CSV Header schreiben + */ +static void write_csv_header(FILE *fp) +{ + fprintf(fp, "timestamp_sec,timestamp_usec,length,sender_mac,message_type,channel,rssi\n"); +} + +/** + * CSV Zeile schreiben + */ +static void write_csv_row(FILE *fp, cits_message_t *msg) +{ + char mac_str[18]; + snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x", + msg->sender_id[0], msg->sender_id[1], msg->sender_id[2], + msg->sender_id[3], msg->sender_id[4], msg->sender_id[5]); + + fprintf(fp, "%u,%u,%u,%s,%u,%u,%d\n", + msg->timestamp_sec, msg->timestamp_usec, msg->length, + mac_str, msg->message_type, msg->channel, msg->rssi); +} + +/** + * Neue CSV-Datei erstellen + */ +static esp_err_t create_new_csv_file(void) +{ + time_t now; + struct tm *tm_info; + + time(&now); + tm_info = localtime(&now); + + // Dateinamen mit Zeitstempel + snprintf(current_filename, sizeof(current_filename), + "/data/cits_%04d%02d%02d_%02d%02d%02d.csv", + tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday, + tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec); + + if (csv_file != NULL) { + fclose(csv_file); + } + + csv_file = fopen(current_filename, "w"); + if (csv_file == NULL) { + ESP_LOGE(TAG, "Failed to create CSV file: %s", current_filename); + return ESP_FAIL; + } + + write_csv_header(csv_file); + fflush(csv_file); + + ESP_LOGI(TAG, "Created new CSV file: %s", current_filename); + return ESP_OK; +} + +/** + * Prüfen ob neue Datei nötig (10 Minuten Intervall) + */ +static void check_new_csv_file(void) +{ + time_t now; + time(&now); + + if (difftime(now, last_write_time) >= CSV_WRITE_INTERVAL_SEC) { + create_new_csv_file(); + last_write_time = now; + } +} + +/** + * C-ITS Nachricht speichern + * + * @param msg Nachricht Daten + */ +void csv_store_cits_message(cits_message_t *msg) +{ + if (csv_file == NULL) { + create_new_csv_file(); + if (csv_file == NULL) { + return; + } + } + + check_new_csv_file(); + write_csv_row(csv_file, msg); + fflush(csv_file); +} + +/** + * CSV System initialisieren + */ +esp_err_t csv_writer_init(void) +{ + // SPI Flash Filesystem mounten + static wl_handle_t wl_handle; + const esp_vfs_fat_mount_config_t mount_config = { + .max_files = 4, + .format_if_mount_failed = true + }; + + esp_err_t ret = esp_vfs_fat_spiflash_mount_rw_wl("/data", "storage", &mount_config, &wl_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(ret)); + return ret; + } + + // Erste CSV Datei erstellen + return create_new_csv_file(); +} + +/** + * CSV System beenden + */ +void csv_writer_deinit(void) +{ + if (csv_file != NULL) { + fclose(csv_file); + csv_file = NULL; + } +} \ No newline at end of file diff --git a/block4_integration.c b/block4_integration.c new file mode 100644 index 0000000..cbaa2d9 --- /dev/null +++ b/block4_integration.c @@ -0,0 +1,111 @@ +/** + * Block 4: Integration und Flashen der Firmware auf ESP32-C5 + * + * Ziel: C-ITS Sniffer Firmware für ESP32-C5 compilieren und flashen + */ + +#include +#include +#include +#include +#include +#include + +#include "sdkconfig.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_wifi.h" +#include "nvs_flash.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "block1_hardware_init.h" +#include "block2_cits_parser.h" +#include "block3_csv_writer.h" + +static const char *TAG = "CITS_SNIFER_MAIN"; + +/** + * Sniffer Callback - Wird vom WiFi Promiscuous Mode aufgerufen + */ +static void sniffer_callback(void *recv_buf, wifi_promiscuous_pkt_type_t type) +{ + wifi_promiscuous_pkt_t *packet = (wifi_promiscuous_pkt_t *)recv_buf; + + // Nur MISC Typ für 802.11p verarbeiten + if (type != WIFI_PKT_MISC) { + return; + } + + // Verarbeite C-ITS Nachricht + if (packet->payload != NULL && packet->rx_ctrl.sig_len > 0) { + cits_process_packet(packet->payload, packet->rx_ctrl.sig_len, + packet->rx_ctrl.timestamp / 1000000U, + packet->rx_ctrl.timestamp % 1000000U); + } +} + +/** + * C-ITS Sniffer aufsetzen + */ +static esp_err_t setup_cits_sniffer(void) +{ + // WiFi Promiscuous Mode starten + esp_err_t ret = start_promiscuous_mode(CITS_CHANNEL_0_MHZ); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to start promiscuous mode"); + return ret; + } + + // C-ITS Parser initialisieren + ret = cits_parser_init(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize C-ITS parser"); + return ret; + } + + // CSV Writer initialisieren + ret = csv_writer_init(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize CSV writer"); + return ret; + } + + ESP_LOGI(TAG, "C-ITS Sniffer Setup abgeschlossen"); + return ESP_OK; +} + +/** + * Hauptfunktion + */ +void app_main(void) +{ + ESP_LOGI(TAG, "C-ITS Sniffer für ESP32-C5 startet..."); + + // NVS initialisieren + esp_err_t ret = init_nvs_flash(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize NVS"); + return; + } + + // WiFi initialisieren + ret = initialize_wifi(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize WiFi"); + return; + } + + // C-ITS Sniffer aufsetzen + ret = setup_cits_sniffer(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to setup C-ITS Sniffer"); + return; + } + + // Hauptschleife + ESP_LOGI(TAG, "C-ITS Sniffer läuft - Warte auf C-ITS Nachrichten..."); + while (1) { + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} \ No newline at end of file