Files
cits-sniffer/main/block4_integration.c
T

229 lines
6.8 KiB
C

/**
* 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 <freq>, set_channel <freq>, stop_sniffer
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <inttypes.h>
#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 <anzahl>\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 <freq>, set_channel <freq>, packets <n>, 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);
}
}