/** * Block 4: Integration - C-ITS Sniffer für ESP32-C5 * * Hauptprogramm: * - NVS + WiFi + 802.11p PHY + Promiscuous Mode * - CSV Writer auf SD-Karte * - USB-Serial/JTAG Console für Live-Ansicht der C-ITS Nachrichten * - CLI Commands: status, chan , set_channel , stop_sniffer */ #include #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 "esp_console.h" #include "driver/gpio.h" #include "nvs_flash.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/usb_serial_jtag_vfs.h" #include "driver/usb_serial_jtag.h" #include "block1_hardware_init.h" #include "block2_cits_parser.h" #include "block3_csv_writer.h" static const char *TAG = "CITS_SNIFFER"; #define LED_PIN GPIO_NUM_28 #define STATS_INTERVAL_TICKS (pdMS_TO_TICKS(60000)) #define BUILTIN_LED_ON 0 #define BUILTIN_LED_OFF 1 /* ---------- Sniffer-Zustand ---------- */ static volatile bool g_sniffer_active = false; static volatile uint32_t g_total_packets = 0; /* ---------- Promiscuous RX Callback ---------- */ void sniffer_on_raw_packet(void *buf, wifi_promiscuous_pkt_type_t type) { (void)type; if (!g_sniffer_active) return; wifi_promiscuous_pkt_t *pkt = (wifi_promiscuous_pkt_t *)buf; if (!pkt || pkt->rx_ctrl.sig_len < 14) return; int8_t rssi = pkt->rx_ctrl.rssi; uint16_t data_len = pkt->rx_ctrl.sig_len; uint32_t channel_mhz = pkt->rx_ctrl.channel; uint32_t ts_us = pkt->rx_ctrl.timestamp; g_total_packets++; // LED blink gpio_set_level(LED_PIN, (g_total_packets % 10 < 1) ? BUILTIN_LED_ON : BUILTIN_LED_OFF); // C-ITS Parser aufrufen cits_process_packet(pkt->payload, data_len, rssi, channel_mhz, ts_us / 1000000, ts_us % 1000000); } /* ---------- Console Commands ---------- */ static int cmd_status(int argc, char **argv) { (void)argc; (void)argv; ESP_LOGI(TAG, "== STATUS =="); ESP_LOGI(TAG, "Sniffer aktiv: %s", g_sniffer_active ? "JA" : "NEIN"); ESP_LOGI(TAG, "Gesamt Pakete: %" PRIu32, g_total_packets); return 0; } static int cmd_chan(int argc, char **argv) { if (argc < 1) { printf("Nutzung: chan <5900|5890|5880|5870>\n"); return 0; } uint32_t freq = atoi(argv[0]); if (freq != 5900 && freq != 5890 && freq != 5880 && freq != 5870) { printf("Ungültiger Kanal. Gültig: 5900, 5890, 5880, 5870\n"); return 1; } set_cits_channel(freq); ESP_LOGI(TAG, "Kanal auf %d MHz ge\303\244ndert", freq); return 0; } static int cmd_packets(int argc, char **argv) { if (argc < 1) { printf("Nutzung: packets \n"); return 0; } int target = atoi(argv[0]); uint32_t start = g_total_packets; printf("Warte auf %d Pakete... ", target); fflush(stdout); while (g_total_packets - start < (uint32_t)target) { vTaskDelay(pdMS_TO_TICKS(1000)); } printf("OK! %" PRIu32 " Pakete empfangen.\n", g_total_packets); return 0; } static int cmd_restart(int argc, char **argv) { (void)argc; (void)argv; printf("Sniffer wird neu gestartet...\n"); stop_promiscuous_mode(); g_sniffer_active = false; vTaskDelay(pdMS_TO_TICKS(500)); g_total_packets = 0; esp_err_t ret = start_promiscuous_mode(CITS_CHANNEL_0_MHZ); if (ret == ESP_OK) { g_sniffer_active = true; ESP_LOGI(TAG, "Sniffer l\303\274uft auf %d MHz", CITS_CHANNEL_0_MHZ); } return (ret == ESP_OK) ? 0 : 1; } /* ---------- Hauptfunktion ---------- */ void app_main(void) { ESP_LOGI(TAG, "====== C-ITS SNIFFER ESP32-C5 ======"); ESP_LOGI(TAG, " Release v2.0.0 — C-ITS Live + SD-Card"); ESP_LOGI(TAG, " Build: %s %s", __DATE__, __TIME__); ESP_LOGI(TAG, "======================================"); // LED gpio_reset_pin(LED_PIN); gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT); gpio_set_level(LED_PIN, BUILTIN_LED_OFF); // NVS esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { nvs_flash_erase(); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); // WiFi 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_ERROR_CHECK(esp_wifi_start()); ESP_LOGI(TAG, "WiFi initialisiert (NULL-Mode / Promiscuous)"); // CSV Writer (SD-Karte) ret = csv_writer_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, "CSV Writer init failed: %s", esp_err_to_name(ret)); } // C-ITS Parser cits_parser_init(); // USB-Serial/JTAG Console #ifdef CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG usb_serial_jtag_driver_config_t jtag_cfg = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(); usb_serial_jtag_driver_install(&jtag_cfg); usb_serial_jtag_vfs_register(); usb_serial_jtag_vfs_use_nonblocking(); usb_serial_jtag_vfs_use_driver(); ESP_LOGI(TAG, "Console: USB-Serial/JTAG @ 115200 bps"); #else ESP_LOGI(TAG, "Console: UART default"); #endif // Promiscuous Mode starten start_promiscuous_mode(CITS_CHANNEL_0_MHZ); g_sniffer_active = true; // CLI Commands esp_console_register_help_command(); const esp_console_cmd_t cmd_status_def = { .command = "status", .help = "Show sniffer status", .func = cmd_status, }; esp_console_cmd_register(&cmd_status_def); const esp_console_cmd_t cmd_chan_def = { .command = "chan", .help = "Change C-ITS channel (5900|5890|5880|5870)", .func = cmd_chan, }; esp_console_cmd_register(&cmd_chan_def); const esp_console_cmd_t cmd_pkts_def = { .command = "packets", .help = "Wait for N packets", .func = cmd_packets, }; esp_console_cmd_register(&cmd_pkts_def); const esp_console_cmd_t cmd_restart_def = { .command = "restart", .help = "Restart sniffer", .func = cmd_restart, }; esp_console_cmd_register(&cmd_restart_def); // register_cits_commands() aus block1 register_cits_commands(); // Hauptschleife ESP_LOGI(TAG, ">>> C-ITS SNIFFER LAUFT <<<"); ESP_LOGI(TAG, "Kanal: %d MHz | SD-Karte: /storage/ | Console: USB-JTAG", CITS_CHANNEL_0_MHZ); ESP_LOGI(TAG, "Commands: status, chan , set_channel , packets , restart"); ESP_LOGI(TAG, "Live-Ansicht: Alle Pakete erscheinen als [PKT#...] auf Console"); uint32_t tick = 0; while (1) { tick++; gpio_set_level(LED_PIN, (tick % 2) ? BUILTIN_LED_ON : BUILTIN_LED_OFF); if (tick % 60 == 0) { ESP_LOGI(TAG, "[STAT] Uptime=%" PRIu32 " min | Total pkts=%" PRIu32, tick / 60, g_total_packets); } vTaskDelay(1); } }